ethereum / EIPs

The Ethereum Improvement Proposal repository

Home Page:https://eips.ethereum.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ERC: Proxy Account

frozeman opened this issue · comments

This proposal has moved to ERC-725 (source).

This issue exists as an archive only.

Original Text
eip: <to be assigned>
title: ERC-725 Smart Contract Based Account
author: Fabian Vogelsteller <fabian@lukso.network>, Tyler Yasaka (@tyleryasaka)
discussions-to: https://github.com/ethereum/EIPs/issues/725
status: Draft
type: Standards Track
category: ERC
requires: ERC165, ERC173, ERC1271 (optional)
created: 2017-10-02
updated: 2020-07-02

This is the new 725 v2 standard, that is radically different from ERC 725 v1. ERC 725 v1 is be moved to #734 as a new key manager standard.

Simple Summary

A standard interface for a smart contract based account with attachable key value store.

Abstract

The following describes standard functions for a unique smart contract based account that can be used by humans,
groups, organisations, objects and machines.

The standard is divided into two sub standards:

ERC725X:
Can execute arbitrary smart contracts using and deploy other smart contracts.

ERC725Y:
Can hold arbitrary data through a generic key/value store.

Motivation

Standardizing a minimal interface for a smart contract based account allows any interface to operate through these account types.
Smart contact based accounts following this standard have the following advantages:

  • can hold any asset (native token, e.g. ERC20 like tokens)
  • can execute any smart contract and deploy smart contracts
  • have upgradeable security (through owner change, e.g. to a gnosis safe)
  • are basic enough to work for for a long time
  • are extensible though additional standardisation of the key/value data.
  • can function as an owner/controller or proxy of other smart contracts

Specification

ERC725X

ERC165 identifier: 0x44c028fe

execute

Executes a call on any other smart contracts, transfers the blockchains native token, or deploys a new smart contract.
MUST only be called by the current owner of the contract.

function execute(uint256 operationType, address to, uint256 value, bytes data)

The operationType can execute the following operations:

  • 0 for call
  • 1 for delegatecall
  • 2 for create2
  • 3 for create

Others may be added in the future.

Triggers Event: ContractCreated if a contract was created

Events

ContractCreated

MUST be triggered when execute creates a new contract using the _operationType 1.

event ContractCreated(address indexed contractAddress)

ERC725Y

ERC165 identifier: 0x2bd57b73

getData

Returns the data at the specified key.

function getData(bytes32 key) external view returns(bytes value)

setData

Sets the data at a specific key. MUST only be called by the current owner of the contract.

Triggers Event: DataChanged

function setData(bytes32 _key, bytes memory _value) external

Events

DataChanged

MUST be triggered when setData was successfully called.

event DataChanged(bytes32 indexed key, bytes value)

Ownership

This contract is controlled by an owner. The owner can be a smart contract or an external account.
This standard requires ERC173 and should implement the functions:

  • owner() view
  • transferOwnership(address newOwner)
  • and the Event event OwnershipTransferred(address indexed previousOwner, address indexed newOwner)

Data keys

Data keys, should be the keccak256 hash of a type name.
e.g. keccak256('ERCXXXMyNewKeyType') is 0x6935a24ea384927f250ee0b954ed498cd9203fc5d2bf95c735e52e6ca675e047

Multiple keys of the same type

If you require multiple keys of the same key type they MUST be defined as follows:

  • The keytype name MUST have a [] add and then hashed
  • The key hash MUST contain the number of all elements, and is required to be updated when a new key element is added.

For all other elements:

  • The first 16 bytes are the first 16 bytes of the key hash
  • The second 16 bytes is a uint128 of the number of the element
  • Elements start at number 0
Example

This would looks as follows for ERCXXXMyNewKeyType[] (keccak256: 0x4f876465dbe22c8495f4e4f823d846957ddb8ce6006afe66ddc5bac4f0626767):

  • element number: key: 0x4f876465dbe22c8495f4e4f823d846957ddb8ce6006afe66ddc5bac4f0626767, value: 0x0000000000000000000000000000000000000000000000000000000000000002 (2 elements)
  • element 1: key: 0x4f876465dbe22c8495f4e4f823d8469500000000000000000000000000000000, value: 0x123... (element 0)
  • element 2: key: 0x4f876465dbe22c8495f4e4f823d8469500000000000000000000000000000001, value: 0x321... (element 1)
    ...

Default key values

ERC725 key standards need to be defined within new standards, we suggest the following defaults:

Name Description Key value
SupportedStandards Allows to determine standards supported by this contract 0xeafec4d89fa9619884b6b89135626455000000000000000000000000xxxxxxxx, where xxxxxxxx is the 4 bytes identifier of the standard supported Value can be defined by the standard, by default it should be the 4 bytes identifier e.g. 0x7a30e6fc
SupportedStandards > ERC725Account Allows to determine standards supported by this contract 0xeafec4d89fa9619884b6b89135626455000000000000000000000000afdeb5d6, where afdeb5d6 is the 4 bytes part of the hash of keccak256('ERC725Account') Value is the 4 bytes identifier 0xafdeb5d6
ERC725Account

An ERC725Account is an ERC725 smart contract based account for storing of assets and execution of other smart contracts.

  • ERC173 to be controllable by an owner, that could be am external account, or smart contract
  • ERC725X to interact with other smart contracts
  • ERC725Y to attach data to the account for future extensibility
  • COULD have ERC1271 to be able to verify signatures from owners.
  • Should fire the event ValueReceived(address indexed sender, uint256 indexed value) if ETH is received.

A full implementation of an ERC725Account can be found found here.

Rationale

The purpose of an smart contract account is to allow an entity to exist as a first-class citizen with the ability to execute arbitrary contract calls.

Implementation

Solidity Interfaces

// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.5.0 <0.7.0;

//ERC165 identifier: `0x44c028fe`
interface IERC725X  /* is ERC165, ERC173 */ {
    event ContractCreated(address indexed contractAddress);
    event Executed(uint256 indexed operation, address indexed to, uint256 indexed  value, bytes data);

    function execute(uint256 operationType, address to, uint256 value, bytes memory data) external;
}

//ERC165 identifier: `0x2bd57b73`
interface IERC725Y /* is ERC165, ERC173 */ {
    event DataChanged(bytes32 indexed key, bytes value);

    function getData(bytes32 key) external view returns (bytes memory value);
    function setData(bytes32 key, bytes memory value) external;
}

interface IERC725 /* is IERC725X, IERC725Y */ {

}

interface IERC725Account /* is IERC725, IERC725Y, IERC1271 */ {
    event ValueReceived(address indexed sender, uint256 indexed value);
}

Flow chart

ERC725v2-flow

Additional References

Copyright

Copyright and related rights waived via CC0.

This is a very useful ERC. I would remove all the Must and Should comments regarding types of keys as it should really be left up to the implementation of the contract.

Some contract types might want to have the admin functions, like claim or addKey be made by some types of admin keys, some might want to make those available to different types of keys, some might want to make the process to addKeys to go through the same process as any execute call will go to. This actually doesn't add much complexity: if you want a contract like that, just make so that only the contract itself can call some functions, and then make functions like addKey be actually just a proxy that creates a proper request to execute them, via whatever mechanism execute needs to go.


function approve(uint256 _id) returns (bool success)

you should either add a second boolean parameter to say either you approve or not, or add a second function called reject

I added the bool to the approve, just forgot that.

Concerning the flexibility of key addition/removals, i added:
"MUST only be done by keys of type 1, or the identity itself. If its the identity itself, the approval process will determine its approval."

Which includes either using key type 1, or the identity itself, e.g. then only the identity contract itself can call those function, and they always go through the approval process.

It's just that I don't believe defining key types should be in the scope of this ERC. For some cases, like a democracy, the strings can represent different types of agents: voters, election officials, ID validators, those who can propose new stuff, etc. For a more hierarchical organization, type can be a number representing their rank: for some smaller is more important, for others, bigger is more important.

The reason to add key types, is to prevent people from running around with keys, which can overtake their identity, but rather only use they action keys on a daily basis. Those wont have the ability to remove or change keys, which reduces the risk to loose your identity all together.

The other advantage is that it allows to define purposes to keys, which other entities or contracts can then use to derive the purpose of a user action on their system. E.g. if key type 23 means award collector, then a game interface knows which one to assign awards to.

I would like to see some details/arguments as to why this benefits from being a standard. In what ways do we gain interoperability benefits from having this standardized? What types of general purpose tooling are we expecting people to build that will need to work with unknown future implementations of this?

Looking over the methods, it seems like a large number of them would qualify as "implementation details" and are not relevant to creating an generic identity management standard. For example, how a particular identity provider does key management is not something that needs to work with many tools, it just needs to work with the identity provider's tool suite. Even some contract that supports 10 identity providers and wants to interface with them all presumably needs to trust those providers in advance, meaning they don't need to build their contract to support arbitrary future providers.

Given the current motivation section, I would recommend that this not be a standard and instead just be a contract/dApp that anyone can write and deploy. 😄

@MicahZoltu I disagree there. If I'd like to be able to use an identity in Mist, it means that I want to create an account, allow that account do things on behalf of others. What I mostly need to be standardized is the addKey, execute and approve. We can use our own private contract, but I think it's nice to try to work together with others.

This needs to be standardized so that other contracts can interact with real world identities, automatically check and verify them. It’s not mainly necessary for interfaces alone. Also this contract represents ONE identity. The addition of claims need to be standardized, so that other identities can issue claims about each other.

Verifying an identity would happen in the following ways:

  • either The calling contract knows the claimtype (are not defined yet, but would be things like address, biometric data etc) and issuer it trusts. Then he simply needs to retrieve that claim and verify that it’s signature contains the address of the identity and the claim number. And checks that this signing address belongs to the issuers identity.
  • or he will retrieve claim by type and then goes and checks the issuers identity claims. This can be done down as many ways as necessary to end up at an trusted claim.

But I assume over time known and trusted issuers will appear so only one check needs to be done.

I might write an extra document to explain all the ways of how one can interact with this contract. But I would like to keep that apart from the ERC itself to keep it easy to read.

In order for there to be value in a standard there needs to be interoperability concerns that are being addressed. We don't need a standard for prediction markets, or a standard for exchanges or a standard for gambling games unless there is a compelling argument as to how one of these things would be better if they were interoperable. There isn't significant value in making it so all gambling games have the same interface, since users will interact with each gambling game via a dApp custom built for that gambling game.

A good example of useful standardization is token contracts. There is value in standardizing tokens so that an application (e.g., Wallet, exchange, etc.) can interact with any token the user provides without needing to know about it in advance or write custom integrations for each token. However, there is little to no value in standardizing how tokens come into existence because there isn't a strong need for a general purpose UI for token management. Each token author can build a token management UI just for their token, end users won't be using this so it doesn't even need to have a familiar interface.

@alexvandesande You have indicated that you want addKey, execute and approve standardized. How would standardizing those add value to the ecosystem? What can you do with those things standardized across many implementations that you wouldn't be able to do if they were not standardized?

@frozeman It sounds like you have a grand vision in your head that isn't expressed clearly in this EIP or discussion. I would love to hear more about it.

As a dApp developer who wants to verify the identity of someone interacting with my contract, I need to go to an identity provider that I trust and and say, "account X claims to be UUID Y, please verify" (or similar) and they would then return true or false. This is certainly useful, but I do not see where in this process a standard adds value. Since I need a pre-existing trust relationship with the identity provider, my dApp won't be accepting any random identity provider that a user gives me. I must integrate my dApp with specific identity providers, and in almost all situations I can think of I will pick one (and only one).

To be really clear, I'm not arguing that Identity Providers are bad. I'm arguing that creating a "standard" (and going through the RFC process) for every useful contract someone can think of is bad. There may be value in this being standardized, but it is not immediately apparent to me and I want you to convince me that standardization adds value.

Edit: In case it isn't clear exactly what I'm looking for, I would like to see a problem statement that shows some problem that can't be solved without a standard. Right now this EIP is missing a problem statement.

Some upfront definitions would be good. What are keys? Are they cryptographic identities? Why not addresses? What is a claim for, and how does it work?

Interface definitions probably shouldn't contain Solidity-specific types (eg, mapping(foo=>bar) baz), but instead the interfaces they generate (eg, function baz(foo) returns(bar);). How it's implemented is an implementation detail for the contract.

I agree with @alexvandesande that principal types should be left up to the implementation. Role accounts are a good thing and should be encouraged, but there's no need for the spec to mandate what roles exist and what privileges they have.

@MicahZoltu I believe the purpose of standardising this is to allow multiple clients (eg, wallets) to interact with multiple implementations of identity providers (Eg, multisigs, etc). Without a standard, you have the current situation, where Mist has native UI for multisigs, but only for its own API, Parity has another, and so forth.

@MicahZoltu i see this needs a lot more explanation. I kept the standard description concise to make it readable, but many of the concepts i introduce here are not apparent right from the start. I will address each of these points here in the discussion, but also keep in mind, as i wrote above; the ERC draft is not finished yet.
I will be giving a talk at the london meet up on the october 11th, where i will lay out my vision for that standard in more detail. This will be recorded and i will post the video here.

First of this is a standard for a self sovereign identity; This means the owner controls its identity and he allows claims about himself to be attached to his identity. There are no identity providers, but claim issuer (or certifiers). Those simply say: "I saw him in person, stored his biometric data, and attached a link on his identity". People who want to verify that they are dealing with a person, either in their contracts, or dapps, websites, etc. can then check on their identity - given they got a signed message from one of its keys - and look for a claim they trust.

But to answer you questions:

  • Why i think this needs to be standardised:
    Standardising this allows other contracts in the future to auto verify users, and implement permission models right in their contract. Standardising also allows other identities, or claim issuers to add claims to an identity. The less important part is standardisation for UI interfaces; But also here we gain the ability to take your identity and make it useful and accessible in Mist, MetaMask, Browsers, Government UIs, border control, community tools and what not... Once an identity is created, it is meant to be used for a long time and over many platforms and UIs, otherwise it can't function as your identity over time.

Do i think all of the current proposed functions need to be standardised? No; i just wanted to give a more or less complete set of functions, which make clear how they interact together.

  • What is an example use case
    Imagine the following: You want to interact with an smart contract of a bank to create an account. They need to make KYC on you. In the openAccount call from your identity, the bank contract can see this call is coming from an identity, so he will:
    -> look for claim type 1:biometric and 2:homeAddress and for a claim issuer they know they trust, like the German state for 1 and the Deutsche Post for 2. As they know their identity contract addresses, they simply do: keccak256(issuer address + claimTypeNumber) and get the index of the claim in YOUR identity.
    -> they retrieve the claim, check that the signed data matches keccak256(YOUR identity address + claimTypeNumber)
    -> Now they check that the key which this data was signed, is still hold by the issuers identity contract.
    -> They got their proof - without that they need to actually see the biometric data, nor the address, as they trust the issuer - and they can proceed in opening an account.

The whole example above, won't work automated and with unknown parties, if these processes and functions aren't standardised.

Another extension of this could be that you have to hop through multiple claim issuers, to reach one you trust, which in return makes you trust all the others, including the one you verify the identity of.

Also every claim issuer, needs to implement this identity interface himself, to make sure he is verifiable himself (and keys can be checked).

@Arachnid concerning key types: If we standardise them we allow many upcoming use cases for keys, as described in my previous comment. Currently i only propose two types: 1 management keys, and 2 action keys. The former is for manage your identity and they should stay safe. There can be n of m required for any change. The latter is for actions in the world, keys which can act in the name of your identity. Those are replaceable, and for everybody who wants to interact with you, should always check of you still hold those keys in your identity.

Claim types in return need to be predefined, to allow somebody who wants to verify you to look for what he want a proof about you.

I choose the word keys, over addresses as this is better understandable in the "off-chain" world. Keys are something we use on a daily basis to get into houses and objects, and the term is used in cryptography as well. Addresses is very blockchain specific. Though your identity contract address - i would call "address".

The current draft allows for all kind of different key management implementations, it doesn't force any, expect that there have to be at least one second step of approval to execute, as stated in the draft, some functions..:

"MUST only be done by keys of type 1, or the identity itself. If its the identity itself, the approval process will determine its approval."

(There is certainly a lot of improvement potential here, and when we think of compatible UIs, we will need to revise that)

Many of the above concepts may not be clear yet, but they are in the description of the ERC as a very concise sentence:

"This identity can hold keys to sign actions (transactions, documents, logins, access, etc), and claims, which are attested from third parties (issuers) and self attested, as well as a proxy function to act directly on the blockchain."

I choose the word keys, over addresses, as this is better understandable in the "off-chain" world. Keys are something we use on a daily basis to get into houses and objects, and the term used in cryptography as well. Addresses is very blockchain specific. Though you identity contract address, i would call "address".

The problem is, 'keys' has a specific use in cryptography, and you're using them to refer to something that isn't a cryptographic key, or necessarily controlled by one. I'd really suggest choosing a different term.

In either case, the EIP definitely needs a definitions section.

I agree we should add a definition section.

Short answer to the above. keys are public keys: Those keys are you hands in the real world, you sign things, you make transactions etc.
Through these keys and a pointer to your identity, others can go check that its really you.
If they want to know things about you: e.g. are you a human, or have an address, then they look on the claims about you by others.

‘Keys’ here can be public keys or other contract, like multisigs and reputation systems. If anybody has a better word for them, I’m happy to change that.

claims :
a.I would suggest a logic that permits explicit approval of claim by issuer - perhaps requiring an asynchronous process.
b. Do we cover a single usage access method such that a third party can prove my info, but only once. Maybe time limited.

@MicahZoltu

There is value in standardizing tokens so that an application (e.g., Wallet, exchange, etc.) can interact with any token the user provides without needing to know about it in advance or write custom integrations for each token.

Exactly. I'd like to be able to login with my uPort identity into Mist, use my Mist identity in Status, or log in with my Status identity on a ether play game or post a blog post in Steemit from my Aragon Company identity. Each one can be implemented differently, just keep some common interfaces.

This is very interesting and it overlaps a bunch with stuff we are doing with uport. Although we have a quite different design I think discussion and standardization around this will be very usefull. I'll give a breif description of our design before I go on.

As the base of our identity we use a very simple proxy contract, see also ERC: Proxy standard. This makes our system very flexible in terms of how you can control an identity.
To control a proxy contract we use a contract we call IdentityManager. The basic idea is that we want a single contract that multiple users can use to control their proxies, mostly to reduce gas cost. Here we have the ability to add multiple users etc, but this is something we want to iterate on in the future.
To issue and lookup claims we have a separate contract uport-registry. The basic idea here is that we want to separate the storing of the claims from the identity itself to a different contract.

I think this ERC touches two very interesting things, transaction execution and claim structures.

Transaction execution

The execute/approve looks promising and definitely something that should be used for high value transactions. e.g. transaction of > 100 eth needs to be aproved by my hardware wallet. But in the case of low value transactions it seems like a bit of overhead, e.g. I need to send two transactions in order to send a tweet on leeroy. Would be interesting to have a system where some execute are automatically approved.

Claims

We've opted for not storing claims in the identity contract itself, this makes it cheeper to depoy identities while claims can still be associated with the identity with the same level of security.
Another thing we have though a lot about is the privacy of claims. Right now there is basically no privacy for claims that are on-chain, which is basically a no-go for a lot of our use cases. Instead we are mostly using off-chain claims which also can be securely linked to the identity (proxy contract in our case). Of course we see the benefits of having on-chain claims as well, and standardization around the format of these is very useful, but they should be decoupled from the identity contract itself. Maybe the claim section could be put into a separate ERC?

I agree with @Arachnid - 'keys' should refer to cryptographic key.

@frozeman Great initiative! This is so needed. It's a great step forward a standard for a self sovereign identity but it will not prevent people from creating more than one identity which is a no-go regarding KYC institution requirement process. Except if the identity public address is linked to multiple trustworthy services.

@overdrev I’m not sure if a Claim permission process is needed, except when an entity wants to know the details of the claim, e.g. see the biometric data stored by the issuer. Then of course we need a async process. I have made some thoughts about that, but this is not really part of this ERC and can be a separate standard.

I see it as follows: claim data (referenced by ‘bytes claim’) is double encrypted by the issuer and me, if somebody wants to see the actual data they request it at the issuers ‘bytes _location’ and request the issuers part to be decrypted, then they come to me and ask for decrypting the second part, which i can always decline.

For b. I’m not sure how a single claim proof should look like, but interesting idea.

@oed thanks for participating, you guys should have actually started that standardization process ;)
Concerning your approaches:

Transaction execution: the excite function is mainly to act as your identity on the Blockchain in the least cases this contract should and will be used for storing and sending ether. If you want to move money and what that to be publicly visible and attached to your identity, use a multisig, or a wallet which is controlled by your keys from your identity .

Claim storage: I do understand you wanted to create a system which is cheap in gas, as uport will overtake most transaction costs in the beginning, but I don’t think this applies for a self owned standard, and would be the wrong approach to that. At the same time when a standard is found and a library is deployed, deploying a contract which uses that library is quite cheap.

Claims themself will be added by others, the owner of the identity will only pay for the confirmation. As I think A real used identity won’t attach every new app, or social network as new claim, those claim additions will be rather less. Things like this will be stored in other Reputation systems or uport like systems and can be attached as a self made claim to my identity, this way the identity can be kept rather raw. The “cool” stuff can happen on other experimental systems.

I’d say there are two main reasons why claims should be with the identity contract:

  1. It allows for on chain verifications and in the best case the contract, which wants to verify, only needs to call you identity once. He doesn’t have to go look on another address, or even outside of the BC. This allows for complex automated authentication systems purely running on the Blockchain.
  2. People want the feeling of having their things on one place, as funny as this sounds but it makes people feel more in control. It’s hard for people to acces their identity through registry contracts, if they don’t fully trust the registry. On top of that this standard allow for many different implementations of identities, which will all be able to create claims about each other.

There is probably more reasons, which don’t come to my mind now.

Concerning privacy: as the claim data is only meta data, the only viable information one can retrieve from your identity is: which claim issuer has claims about me (e.g. the German state, or Vitalik claims something about me), and when that data has changed.

This can be an issue, if I don’t want anybody to know I live or are German, but we share a lot more information on social networks daily. Also privacy focused claim provider can pop up, which claim things, like address etc globally, but are trusted by many. Then the only thing it leaks, is that you are privacy focused :)

@bneiluj people will have more than one identity for sure, as we just start to experiment with this, but once your have gone through the effort to get claims about biometric data and address, etc. you will treat this identity as more valueable. As long as you can add new claims of importance to more than one identity, that’s fine too. The person verifying your identity doesn’t need to care, as long as he can trust the claim issuer.

@Arachnid I added a definitions section. I’m still open for better names for keys.

@frozeman Anything other than keys, really. I'd suggest 'principals', for instance.

It's still not clear to me what goes in this field. The definition says "public keys", but contracts don't have public keys. What would the 'key' for a contract be?

@oed

I need to send two transactions in order to send a tweet on leeroy.

Actually I don't think that's how I would recommend. You can sign your tweet with any account, publish and say: "I am tweeting in behalf of foo.eth". Then the tweet app can check either that account is listed in one of these keys. No on-chain transaction required.

  1. Will the claimTypes enumeration be maintained as part of the standard?

  2. Claim location might be better represented as claim uri, even if it involves a hash. But is a URI scheme involving a hash defined for all cases? I saw a lot of discussions in IPLD / IPFS about URI schemes, and in that community it seems inconclusive.

Example discussion: ipfs/ipfs#227

https://en.wikipedia.org/wiki/Uniform_Resource_Identifier

Is the plan to allow claimTypes to not only be used to verify an identity but also to verify information about an identity?

claimTypes could be used to confirm accreditations from institutions, attendance at events and place of work. So for example if a decentralized Uber was created and this dApp only wanted drivers who had gone to driving school, then claimTypes could be used to confirm this. If the drivers received the proper claimType from a credible driving school they could be drivers for this decentralized application. So claimTypes if used this way could automate the process of checking the credentials of identities.

I understand that you want to keep the contents of the ERC "just the spec" but reading over all of the comments here I think the lack of a really clear problem statement and really clear and targeted solution is causing confusion. It sounds like there are several different interpretations of what this ERC is about in this discussion and everyone has a different image in their head as to what this will be used for.

@frozeman Can you provide a problem statement or user story as a starting point? Describe the problem that you are trying to solve (without describing the solution as part of the problem). I just tried to think of an example problem statement that requires this system but was unable to come up with one, which is why I'm struggling to understand the value of this being a standard. An example problem statement for a token standard (pre-ERC20) is:

I want to be able to build a smart wallet that can control any token the user desires, including future tokens that don't yet exist. The user needs to be able to transfer tokens into the wallet and out of the wallet without risk of the tokens being trapped in the wallet contract. Currently, each token has a slightly different API so it is not possible to build a wallet without designing it to support each token, and such a wallet would not support future tokens (with as of yet unknown APIs).

Note: Be prepared for me to offer alternative solutions to your problem statement that don't involve a standard. 😉

@jpitts thanks for sharing.
I would suggest coming up with a set of claimTypes and new standard additions can come up with new ones, that’s why it’s a uint256. We could also leave the type description out of here and make that a totally different standard.

URI makes sense, I will change that and also change it for a string for now.

@CDsigma your use case it exactly right, you can have people and institutions claiming things about you, and you can allow those claims attached to your identity. And yes; you can never verify an identity if you don’t verify claims about it.

@MicahZoltu I agree that it doesn’t seem to catch on right away what the use of this ERC is, though I brought already a few exmpakes which cover your points. But I can try to reformulate:

  • see KYC, currently everybody collects all information about you separately, to make sure they know who you are. E.g. banks, credit services, or any service which needs to have KYC. A standard will help in so far that everybody can auto check certain clams, and therefore don’t need to store your actually details about you anymore, as they - as long as they trust the claim issuer - don’t need to have the actual information. The current overcollecting is because of lack of a better system.
  • imagine you want to prove you are over eighteen. A trusted entity can add a bit ask as claim, which contains a bit that states that’s you are over eigtheen without revealing your age. Again the trust here is moved to the claim issuer, rather than the person want to prove something about themselves. In large th is can create complex trust graphs.

There are plenty more, and all come down to yourself wanting to prove something in front of others. And the claim model solves that: you can also take a look at https://sovrin.org/wp-content/uploads/2017/06/The-Inevitable-Rise-of-Self-Sovereign-Identity.pdf as they describe a similar system.

So in short the solution the ERC brings:

  1. I want to prove something
  2. Everybody can verify claims, as they know how and where to look - automatically.
  3. This can go as deep as it needs to reach a trusted claim issuer (jumping from issuer to issuer)
  4. Your identity can be taken to any interface which needs an identity, without creating a new one for every app.
  5. Smart contracts can verify claims automatically
  6. You can act outside of the Blockchain and third parties can check your identity on chain.

I am not aware of any system, which doesn’t require a central authority that allows to create a self sovereign identity. And I am unclear how this can be solved without a standard.

The token standard is quite the same. Everybody could have made their own tokens, but only by creating a standard we are able to use them anywhere, and with erc223 we will be able to have those tokens interact. And as you brought up ERC20 a lot, I assume you are aware that I proposed that standard.

Also for this standard, the target is not mainly the UIs, but other identities and smart contracts. Though UIs are as important, to be able to take your identity around.

@frozeman
Sorry I think I missunderstood what you are trying to do. Let me see if I understand correctly now.
Transaction execution: So this is more something along the lines of an identitfier for an identity that you can attach accounts to? It would mostly be used to attach claims to and send claims from. Uport are trying to come up with something similar, but without relying as much on on-chain logic to do so. Check out the work of the Decentralized Identity Foundation, in particular the DID spec which uport will be compatible with.

Claim storage: So this will be kind of like a personal registry of claims associated with your identity? If it's only meta data that is being stored on-chain, where would the claim itself be stored?

Right now claims are stored off-chain by the users themself in uport. One of the main reason for putting a claim on-chain would be if it needs to be verified by a smart contract. The smart contract is likely to want to know something about a particular account that it is interacting with, rather than the identity itself. Having the claims in a separate registry makes it possible to make claims on any kind of account. Not just this very specific identity contract. This opens upp for the possiblitity of proving something about an account with a zkp without revelaing which identity owns that account.

As for your two main reasons for keeping it in the identity contract:

  1. I don't really see a problem of having to look at another contract, as long as it's standardized, maybe accessable from a ENS record? Complex automated auth will still be very much possible.
  2. The end user will not know or care about how many contracts are involved. The end user will likely not even know what a smart contract is. The registry would of course be designed so it can be interacted with in a trust-less way.

This being said I can see some benefits of putting claims in an identity contract, but for the reasons I stated above I don't think that's the way to go.

Btw, you should also check out the work being done on verifiable claims

@oed thanks for the links, that looks very interesting and is very similar to what i am trying to do here as well, but with a purely on chain logic. What i can see every body in this space has come up with, is attributes, or claims and keys as actors. Same as me.

Let me try to break down the contract:

-> keys: public keys, or other owned smart contract address, which can interact in your name

- keys are there to prove identity ownership
- keys can hold money and act on the blockchain, and can be traced back to this identity
- smart contracts owned by this identity can be extension systems to the identity, e.g. reputation systems

-> execute: A function to allow this identity to act directly on other smart contracts, to be an actor "on-chain", including holding and transfer of ether.

-> claims: can be added by others, and verified by others. The claim content is stored off-chain, or onchain, but this is not defined here. Important is that the claim has to a have a proofable piece (which here is the signature) and a link to the claim, as well as the issuer.

- claims can requested to be added by anyone.
- claims can only be approved to be added by the owner of this identity
- claims can be removed at any time by the owner of this identity
- claims can be altered by the issuer, punishment would be removal (OR we add approval from the owner as well)

To compare that to the DID, its similar, just that its all in a smart contract and verifiable on chain.

To compare that with the W3C verifiable claims, its basically the same, though we can try to align them even more.

Also to be clear this is not standardising how claims can look like, how the content is stored, or where. Claims can easily be DDOs for example stored on IPFS. Also how identity verifications are handled off chain, e.g how the message will look like when signing off chain and including your identity address on chain. So there is a lot of defining necessary. This ERC mainly should give a very slick framework to put all those claims and claimtypes and keys inside.

Concerning the registry and the identity object (DID vs. DDOs), there can sure be a registry on top which holds the addresses of many identity contracts, e.g. governments could this way group citizens etc. but i don't see a need for that in the basic identity spec.

I am open for a call, to discuss that in person, as i see some misconceptions, or i myself have some.

We've been researching and prototyping a solution for identity in the META Network for the last few months and make use of a lot of the same primitives in this proposal and other projects. Our current implementation uses the ENS to register a subdomain to an identity owner's public address, which resolves to a content-addressed object (eg. stored in Swarm, IPFS) where the identity's metadata (or claims) can be retrieved and verified against signatures on that data. This way we utilise an existing standard and minimise what is stored on-chain.

Given how much of an essential component identity is to a system or network, it would be great to see a flexible standard that developers could build on - we know first-hand how complex this can be! If it can incorporate/accommodate other efforts (like W3C standards) then all the better.

@lukehedger looking forward to contributions.

I just had a fruitful in person discussion with @oed and we came upon with a few small alterations:

  • I removed the changeClaim, as addClaim will do the same, and SHOULD trigger already the approval process.
  • i added getKeyType function and getKeysByType, as well as getClaim and getClaimsByType to allow easy retrieval.
  • I added more key types 3: claim signer, 4: encryption key, which we can debate to change them or add more.
  • i added the bytes claim to the signature of the claim, so that it can't be altered by the claim holder.
  • We were thinking how this idenities could be converted to DDOs (DID descriptor objects), see https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-fall2016/blob/master/draft-documents/DID-Spec-Implementers-Draft-01.pdf for examples of DDOs
  • We were talking if its best to move the claim holder part (Identity verification in the spec), to a separate spec, which this spec then inherits. The reasoning is that there can be claim holders, which aren't themselves identities. E.g. a smart contract about which a validity claim is issued.

It would be really good if work on the holder spec is done first, so that its a good basis, for #725. I will create an issue to discuss this spec part in the coming days.

@frozeman
I like the proposal, also, as already pointed out in this discussion, I would see the need to define a standard set of claimTypes. This can be done by defining a low-range of well known types: i.e. 0 - arbitrary_number also to be defined in this ERC). As the number 256 Bit number is big enough, we could also think about using a bit-mask to organize topics and sub-types or even claim multiple types as once... just a thought.

I also think some details are missing regarding the claim (bytes) storage and access.

... Also a question for a better undestanding:
Regarding the approve function, can you hint out what do you mean by "Triggers on successfull claim addition Event"

Does it mean that if the approve was called by the identity itself or a type 1/2 key, the approve function is automatically called by the Contract, as a self verified claims do not need to be approved? If so, please point that out.

To add to @frozeman's comment it might be good to have an example of how this might be used. Let's assume accouont A, that implements the "Claim Holder" part (Identity verification in the spec), wants to call a smart contract C. C requires everyone that interacts with it to have some biometric data verified by verifier V. The interaction would go like this:

A calls a method on C. C calls A.getClaimsByType(1), finds the claim issued by V, then uses ecrecover to get the public address k of the signer of the claim. It can then call V.getType(k) to verify that the identity V owns the public address k.

Worth noting here is that i getClaimsByType returns more than one claim this might become a quite costly call. One way around this would be to check which claim the contract needs and include the claimIndex in the method call.

As noted this allows for smart contracts to receive and use claims if they implement the "Claim holder" interface. But the smart contract wouldn't need the Identity part of this ERC since it can never sign claims anyway.

@oed
For this claimIndex on execution to work, the Caller also needs to know V, which may not be known in advance, or may even be a set of valid Claim issuers [V,W, ...] , meaning that C must make publicly known their trust set, correct?

@m-schmoock since C is a smart contract V will be publicly known.

@oed
It sounds overcomplicated, but for this to work in a generic way, there needs to be an additional interface for C (maybe called IdentityConsumer) that declare the set of issuers [V, W, ...] a Contract C is trusting.

@oed thanks for this example, though i would make a small correction: C doesn't need to call getClaimsByType, but instead getClaim, as it knows which claim issuers it trusts, it can generate the index using keccak256(address issuer_address + uint256 _claimType) beforehand and pass it to getClaim. After that it ecrecover's, and checks that the public key k is in fact still hold by issuer V.
If the identity doesn't have a claim from that issuer, its anyway not able to pass..

@m-schmoock Every claim addition request should have a approve required. Obviously for the standalone claim holder standard it wont be like this, but for an identity it should. Technically speaking, its up to the implementation if they adhere that, thats why i changed it from "MUST" to "SHOULD create a pending claim...". On the end this contract doesn't have validity because people are forced to use that standard, but because claims are properly signed <- Thats what other contracts can trust.
Defining the approve function here, is mainly to make sure it is interoperable in all interfaces, if some implementations won't require approve for execute, thats up to them. E.g. deportations might solely rely on one multisig being the soley owner.

@m-schmoock C Surely needs to have predefined issuers it trusts, otherwise it can’t autoverify any claim. But for unknown claim issuers it could start an async manual process which involves people or other off chain systems.
But I don’t think the claim issuer needs to be standardized, the process needs to be described for sure, but ultimatively it’s up to any contract what verification process they really trust.
The simplest version would look like the following:

  1. getClaim by index, which is the type for a trusted issuer (keccak256(address issuer_address + uint256 _claimType))
  2. Ecrecover signature, retrieve address k
  3. Check if k is still a key hold by the claim issuers identity contract (issuer address)

That’s all it needs to verify an identities claim.

@frozeman I get the point. This will work for a known set of V's, and there will be ways to get there. Helpful i.e. for checking identity/user access to dapps and such, which will probably be the first but not the last usecase.

I think in reality what we will face is the need to share trust in a broader sense. Just like when multiple companies would trust each others KYC Claims on identities. This will have a real-world benefit today, and complexity related gas costs would easily be covered by not having mutliple KYC video-ident sessions. What I mean that there will be the need to have a large set of V's in reality, just like we have today in our OS/Webbrowser root CA stores.

A concrete usecase for this would be: Allow access to anyone that has a KYC video-ident (or better) from a publicly known company that is: a bank, a telco, a ...

We should be clear about the expected use cases, meaning to support many trustful Issuers, even more identities, but each identity will have few/handful claims (at least so I think). Having C calling keccak256(address issuer_address + uint256 _claimType) for all known issuers maybe too costly if done within a execution/proxy call.

Maybe, what also would be helpful to get this of the ground, is to give the issuers incentives when providing claims on identities. This can be optional and paid by the ones checking the claims, maybe offchain when the uri data is fetched. This will grow the identity ecosystem faster with a larger set of economically useful claims.

Feel free to correct me if I'm getting to far off from the basic idea, but that's why its important to identify the usecases and relations precisely in the problem statement of the proposal.

@m-schmoock your thoughts are valid.

Concerning: pre-known issuer. I think there is no way around it for on chain auto verification to know the issuers a contract trust, and may have to check multiple ones of those. Even checking a few of them should be relatively payable. Also think that the person who wants a service is paying for the gas, not the contract which is called.

I could also imagine that some contracts will go n dimensions deeper, and hop from claim to claim issuer to claim and again claim issuer, until they find a trustworthy one. All this is thinkable.

I would not want this ERC to try to create monetary incentives, as this is not the purpose of this ERC. Incentive systems can be created on top of this standard, once we have a valid one.

@frozeman I totally agree. Incentive systems can be created on top of this standard !

@m-schmoock It could be used for creating unique identities leveraged by trustworthy claim issuers or based on transactions history like Trustlines Network / State Channels. I'm behind this NGO identity project IDbox so it's a fantastic EIP for projects like that.

I didn't say this to be part of this standard, but rather think about how this can/will be done in the wild. Don't underestimate this, as it can be a huge advantage as a side-effect to this proposal. I don't like propretary paid stuff probably even less than you think ;)

I moved the Claims part into its own ERC: 735. Lets discuss details there, the current standard requires only slight changes to #735 to add the approval process.

I added I added uint256 signatureType to #735

@frozeman we missed you at the Rebooting Web of Trust meeting last week. I was asking who was going to summit the DID method spec for ETH. Will you write it up using this template?:

https://github.com/WebOfTrustInfo/rebooting-the-web-of-trust-fall2017/blob/master/draft-documents/DID%20Method%20Spec%20Template%20Definition.md

I started a DID method spec on top of IPFS called IPID. The draft is here:

https://github.com/jonnycrunch/ipid

other examples are:
Sovrin, Veres one, btcr

cc. @christianlundkvist, @talltree

I would ask that as the community build out this powerful capability that we remember that sometimes it is important to be able to fake your identification, hide your past affiliations, and be "un-remembered". For example, in the face of an oppressive government regime, as one flees persecution, one would not want to be tagged with an immutable, unfakeable identifier. I wrote about this issue here: https://medium.com/@tjayrush/be-careful-little-brain-what-you-code-6ad4d5fb9d9b. I think this part of the equation is important and should be openly discussed.

@jonnycrunch can you connect me in skype and we have a chat? (mine: frozeman.de)

@tjayrush i fully agree. But you could always start a new life with a new identity, or ask one of your former claim issuers to sign the new identity or just a key instead.

Do you have any other ideas? (ps. didn't read your blog post yet)

I added a Additional References section.

@frozeman I don't have any ideas about "un-remembering", but I'll share if I do. It's very interesting.

commented

if still looking for a replacement term for 'key': idkey, idnkey, inkey, stub, epigraph, signkey, keychain

@M41 seems keys in this context are basically Ethereum accounts, why not use "accounts"?

@alexvandesande actuallythats what I want to prevent. This standard can and should hold keys of non ethereum types as well ideally, or it’s 20bytes hash at least. And currently that can be also contract addresses. But the more flexible we are the more open this standard will be.

@tjayrush I’ve read your article and I do see what you mean. Let me come up with a possible implementation solution for this standard:

As this standard in most cases stores references and not the data directly, I ALWAYS have to authenticate myself in front of a third party and men know WHICH identity I have.

This is the step where the third party gives me a challenge (random string) and I sign it incl my identity address. This way I point them to my identity in the first place. Only form there he goes on to check claims and may retrieve the actual claim data, e.g. biometric data to compare with my physical person.

I could technically always sign with a different key which belongs to a fake identity, and as long as the claim issuer for biometric data is not giving everybody access, so they can go from biometric data to my real identity, then I would be safe to use any new created identity.

The reason why this wouldn’t happen in a normal functioning society, is because I want to keep my identity for as long as possible, to build up reputation.

So the flaw here lies within the claim issuers we trust, they could technically always reveal who we really are. So we should move to decentralized claim issuer models, which perfectly fit in this standard as well.

@frozeman The idea of a standard behind identity of the blockchain makes complete sense. Public keys being verified via a 'claims' system to validate a public key's authenticity would make sense for physical objects as opposed to simply human and machine identity. An example use case of this would be by using ERC-725 in conjunction with ERC-735 this standard could be used to prove the unique identities items that are manufactured and passed along a supply chain.

The addKey & removeKey functions could correspond unique identifiers to physical object in terms of authenticity and the actors across a marking process on the supply chain dependent on the key types. The transaction cost of this contract may be high but dependent on the item itself it justifies a steep transaction cost to execute functions on the contract. The execute & approve functions are interesting as it opens up the idea of allowing tokens to execute the claims process.

One use case which is the project I have been developing(https://devery.io) looks at physical products identified individually via public keys on the blockchain. I could see this standard being built upon for that specific use case among others. I was initially writing out a very similar spec until I came across this standard which would make a lot of sense to build upon for my implementation. I'm very interested in aiding in the development of this standard.

@MicahZoltu Apart from my project, there are a number of other projects aiming to uniquely identify products using a identity based blockchain implementation. A standardised approach to this would make a lot of sense as it would allow unification between competing physical product identity systems much like ERC-20 has done for tokens.

@alexvandesande In my mind, the term 'key' is more generic to allow the account name to apply to a number of varying identities whether it be an object, machine or person. It distinguishes the keys from typical Ethereum addresses, despite that "accountId" is another suggestion.

@frozeman Does this accurately summarize?

Functional society:

  • centralized third party claim issuers are okay because regime can but will not force revelation of sensitive information

Dysfunctional society:

  • decentralized third party claim issuers are the only truly safe option otherwise regime will force revelation

Current design anticipates (but does not require) fully decentralized third-party claim issuers.

How about calling them 'Chink'. To look through a chink in a doorway give a tiny limited view, but nevertheless a true view. . 'Can you send me your passport chink please ' Key confuses to much in technical / crypto context IMO. And it's a word that people in the (English) street will be able to say. And it's just as good as a 'tweet' or other thing that has entered everyday speech...

@tjayrush it kind of goes in this direction, yes. This standard itself doesn’t care if the claim issuer is centralized or decentralized. It only and will depend on how people will use it.

@andrewrd you interestingly use this standard very different. I for example would see the keys not as identities on the object itself. I would rather add a claim to the objects identity, which is then containing the ID.

@frozeman

  1. Might I suggest combos rather than keys. It means the same thing but in a different way. A chink is a weakness (chink in the armor)

  2. Would this make ENS names much more relevant? It seems so. Also, on the ENS gitter they mentioned adding an identity text string to the resolver (email, etc)

3 Am I correct in reading that if you lose your "combo" but not your wallet keys you can recover with new combos like in uport

  1. I wrote an article on identity on my website (http://ethereumusecases.com/2017/10/05/identity-applications-use-case/). Would this standard complement or partially replace what uPort and Civic are doing? I think I read complement.

  2. Finally by keeping a bit more on chain this may be a gas guzzler (relatively)

Fully open to speaking off line or whatever

@frozeman I'm co-chair of the group writing the DID spec and method spec template (W3C Credentials CG). I'll PM you to offer our help integrating this as a DID method spec.

@kimdhamilton thanks, but the next three weeks will be busy (devcon3 upcoming)

@RexShinka i will take a look at your article. yes the idea is that some keys can replace keys, and others not, but are able to sign. This can only be a recommendation, as people aren't forced to use the standard as describes, they will still be compatible if they name the functions right, so security is only something this standard can recommend, not enforce.

Concerning gas cost. It shouldn't be more expensive than other on and off chain actions. The only cast costs incurred are here the adding and removing of keys and claims, which i don't expect to happen often.

In a few cases you will actually through your identity, but as this would be super visible, you probably wouldn't want to do that all the time, but just in some cases, like adding claims to others (e.g. if you're an institution)

Concerning uport and civic. Its up to them to adopt or support a standard or not, but they doing a great job when it comes to building UI and tools for identities. So if this standard (which ultimately is just an empty shell) gets adopted and used, due to its ease of use and functionality this will be adopted by them anyway.

For reference, i create a wiki for collaboration on advantages and problems of claim registry vs attached claims: https://github.com/ethereum/wiki/wiki/ERC-735:-Claim-Holder-Registry-vs.-in-contract. This is mainly interesting for #735, but also relates to here obviously.

Regarding approve function, its described to approve a claim or execution by n of m managers and maybe n of m actors.
This makes Identity look like a MultisigWallet, while this is not a problem, I find it out of scope. Also, this would make all Identity following this ERC be cluggered by need of approvals. Having this design is good for many use-cases, specifically because most interactions envolves actions on behalf of an Identity.

In order to make Identity less specific, I would prefer isolating the permissioning rules, such as multisignaure, daily maximum values, and more (anything) in a separated contract for interfacing the permissions for that app/actor, for this I suggested a new ERC #745
The approve requirement would be specific from a MultisignedPermission.

Having this abstraction gives more freedom to dapps developers develop their own permission contracts, which need to be trusted (and open-sourced) by the dapps, while other logic could still be closed source without shading the permissions of that contract.

===================================
|  Dapp request permission to:    |
|  - call dapp.eth:buyService()   |
| up to 1 UNI per day.            |
|  - call otherapp.eth:doStuff()  |
|---------------------------------|
|  [Accept] [Read Src] [Reject]   |
===================================

I see that specification wants that the same approve function approving different things, but the interface defined is incompatible. Should be all bytes32.

contract ERC725 {

    uint256 constant MANAGEMENT_KEY = 1;
    uint256 constant ACTION_KEY = 2;
    uint256 constant CLAIM_SIGNER_KEY = 3;
    uint256 constant ENCRYPTION_KEY = 4;

    event KeyAdded(address indexed key, uint256 indexed keyType);
    event KeyRemoved(address indexed key, uint256 indexed keyType);
    event KeyReplaced(address indexed oldKey, address indexed newKey, uint256 indexed keyType);
    event ExecutionRequested(bytes32 indexed executionId, address indexed to, uint256 indexed value, bytes data);
    event Executed(bytes32 indexed executionId, address indexed to, uint256 indexed value, bytes data);
    event Approved(bytes32 indexed executionId, bool approved);

    function getKeyType(address _key) public constant returns(uint256 keyType);
    function getKeysByType(uint256 _type) public constant returns(address[]);
    function addKey(address _key, uint256 _type) public returns (bool success);
    function removeKey(address _key) public returns (bool success);
    function replaceKey(address _oldKey, address _newKey) public returns (bool success);
    function execute(address _to, uint256 _value, bytes _data) public returns (bytes32 executionId);
    function approve(bytes32 _id, bool _approve) public returns (bool success);
}

@alexvandesande , I imagine that we would need something like this https://screenshots.firefox.com/FtDXF9fRryIfVBnD/github.com
Each one of those 3 permission would be one smart contract (* or one to all 3) specifically to handle those permissions.
That's because each one have totally different behavior, and they work like adapters between Identity and DApps.
I'm sure this design can be adapted even with having a execute-approve in the Identity, but I see that all approve/execute would be possible to be done in a separated contract. For example, if we need the Management of Keys to be multisigned, aswell for the Claims.

In the case of Claims I would agree that would be handy to have inside ERC735 the approval of claims added by third parties, so if an allowed claimer start claiming you are something you don't approve, then this won't be added to your Identity. Of course this could also be done in a separate contract, but the process of addClaim->approveClaim are 1. not often, 2. not related to Dapp interaction, 3. fixed behavior.

The way this standard is written allows for a lot of flexibility. In the approval process it only says SHOULD and COULD, but not MUST. This way this Standard can be implemented having no approval, having a n of m approval. Also 1 of 1 is the same as passing directly, e.g, for key additions and executions.

The claim addition itself in the context of an identity must definitely have at least one approval. While in ERC #735 it is not necessarily required. This is because a contract can allow claims about himself, without needing an approval.

Also this standard does not necessarily need to be implemented in exact detail, as long as the functions which other contracts interact are correct, it will be a working ERC 725. As described right now any interface should be able to deal with it automatically, if it has one/multiple or non-approval.

So therefore I am not 100 % convinced that #745 is necessary (also the ERC title is a bit to generic?)

@3esmit Could you be more specific about the execution ID? Where do you say it is not the same?
Thanks for your effort by the way.

Could you be more specific about the execution ID? Where do you say it is not the same?

@frozeman What is the function to approve a Claim? The same used for approval of executions? If so, would be better to have the execution id encoded as a bytes32, so I can check internally at approve what call regarding it is about.
Otherwise, how approve function will be sure that the approve is about a Claim, and not by a coincidentally same pending id of an execute of addKey? Or will the uint256 addClaimId share the same nonce as the uint256 executionId?
In bytes32 we could do something like keccak256("ClaimApproval",issuer,type") and keccak256("Execution", to, value, data), the strings in the encoding could be safely removed as would never collide even without them due different number of parameters.

About ERC745 the objective of it is removing the approve logic from this contract, or from any other, and standardize a permissioning contract that is understood by UI clients and even it's extendability would be better understandable.
Encapsulating the permissioning logic make easier to audit the external permissions at our identity, and makes easier to have complex permissioning rules.
The main problem with having the approval process inside identity is because the needs of complex permissioning will lead to users setting their security to low because the other options don't work or having extremely complex Identity contracts that deal with function signatures and different number of signatures needed depending on the call.
One example of the problem of having these rules in ERC725 is multisig-wallet.sol with daily limits that was written before ERC20, and we have daily limits only for ETH.

I see that there is possible to support both a simple internal action-key permission logic, and use it as key into a complex permission contract as I'm describing in #745

About Keys.. Can a Key (address) be simutaniously MANAGEMENT_KEY and ACTION_KEY or any other key? Or once an address is defined as a certain type of Key, it can only be that type of key? If so, why? If not, why not?

If willing to support one-to-many address->key we would need to change the functions removeKey and replaceKey to include aswell the key type.
If not willing to support, it should be clear in the ERC that some error or other behavior would happen when trying to define a key to an address that is already an other type of key.

I want to implement a Identity contract that contains no Multisig on it (instead I'll be using a Permission Contract is a Action Key), I also want to support this standard.

The problem is that function execute(address _to, uint256 _value, bytes _data) public returns (bytes32 executionId); does not return boolean. I could return executionId as 0x1 if success?
approve function will have no behavior (maybe only approve claims).

Will my Identity contract still be compilant if it returns 0x1 at execute on success and 0x0 on error, and approve does nothing about transactions?

Also, ERC725 is describing about function execute(address _to, uint256 _value, bytes _data) returns (uint256 executionId)

SHOULD require approve to be called with one or more keys of type 1 or 2 to approve this execution.

Returns executionId: MUST be send to the approve function, to approve or reject this execution.

It SHOULD require approval or it MUST require approval?

Hey guys! We've started the draft implementation of #725 and #735 in both Solidity and Viper. Special thanks to @jacqueswww and @3esmit for whipping them up!

https://github.com/status-im/contracts/tree/master/contracts

Hi folks. Great to see this moving forward! We've done quite a bit of related research/dev over at Deloitte (https://github.com/SmartIdentity/smartId-contracts). Standardisation across identity implementations will be very useful, keen to contribute.

A few initial comments (and apologies in advance for not having mastered github formatting...):

Overall Scope
Is this standard intended for use to represent corporate (or other non-human, non-machine identities)? I believe it is (or could be), and so I suggest extending the the initial abstract to include other entities, particularly organisations/groups.

Key loss management
Agree with the approach to role specific keys. Could you outline thinking on mitigation of key loss? An action enabling recovery in the case of lost management/identity-owner keys may be needed. Something like the ability to nominate a set of override keys (m of n) which can invoke special actions such as "freeze" (in case the integrity of one or more keys is in doubt). Then for example if frozen, the only available action is "unfreeze", "replace management key", or "migrate" entire contract to new identity key (which requires further elaboration). I also like the uPort proxy model which overcomes some of these concerns.

Claims
What is the rationale behind requiring approval of claims?

Negative claims: By requiring approval for externally submitted claims (and by allowing the identity owner to remove claims submitted by others) we go some way to preventing the storage of unwanted or negative claims. But we should recognise it will be trivial to develop alternative methods for asserting tracking and verifying negative claims in relation to an identity (indeed the revocation of a previously approved claim is a form of negative claim).

Claim data structure
This is one area that concerns me. It looks like the proposed on chain data in relation to a claim could be used to identify:

  • The type of claim.
  • The issuer of the claim.
  • The date the claim was applied/revoked.

IMO this is too much information to expose. I think the intent is to enable fully in-chain assertion and verification. There are scenarios where this may be required, but I think in most cases this model is not needed (and in some cases it could be a risk). Bear in mind we assume each user is carrying their key (probably on a phone), so why not store the sensitive attribute data in the same secure off chain location, with just the (merkle) hash of each claim on chain, then allow the user to choose when and where they reveal claims (either partially or in full).

In Europe we have regulation due to land in Early 2018 (GDPR) which will impose some considerable obligations on organisations in relation to customer data, one of which is the right of a customer to request removal/deletion of any personal data a company has stored in relation to them. Given claim transaction data will remain in the blockchain indefinitely, the question of how much data is revealed on chain needs to be very carefully evaluated. I'm not convinced an enterprise could comfortably adopt the currently proposed claim format.

Identity spam
Any thoughts on the risk/impact of spam (claim) transactions? Options we considered included the ability to set a user defined, possibly refundable, fee for certain interactions with a contract.

Backward/forward compatability
This also touches on the need for a migration action. The contract spec will likely evolve, people will want to upgrade and a way of linking existing claims with a new contract will likely be needed. Again would be good to understand thoughts/approach to this.

Would love to discuss in more detail...

How does someone reviewing an identity’s claims know what the claim types are?
I suggest linking the identity contract to a claims registry with the following property.

claimTypeRegistry: address of the contract that registers claim types

The claimTypeRegistry can be a very simple contract like the following that emits an event rather than store data in the registry contract.

contract ClaimTypeRegistry
{
    uint256 claimTypeId = 0;

    event EmitClaimType(uint256 claimTypeId, string description);

    function registerClaimType(string description) public {
        EmitClaimType(claimTypeId++, description);
    }
}

The claimTypeRegistry could optionally include the schema of the claim data being signed.

The point here is different networks/communities/jurisdictions can agree on different claim types.

@naddison36 (Re: How does someone reviewing an identity’s claims know what the claim types are?)

Unsure if this was a question to me, but if so, it's because - unless I am missing something - it is recorded in the claim structure (see ERC735) and could therefore be obtained through interrogation of the chain, or via getclaim () etc:

struct Claim {
    **uint256 claimType;**
    address issuer; // msg.sender
    uint256 signatureType; // The type of signature
    bytes signature; // this.address + claimType + data
    bytes data;
    string uri;
}

@frozeman to add to my prev comments, I've tried to re-summarise the point around privacy.

In general - It should not be possible for someone interrogating my identity to be able to identify either the signer of a claim, or the claim type, unless I have explicitly chosen to make this information to be available. I think the baseline should be 'very private' with options to reduce privacy where desirable within the same standard.

  1. Avoiding unwanted interrogation of claim types: I recommend claim type is not stored on chain, or is optional. If mandatory it will be useful if this can be set to either a generic or hashed value which can be used where claim type is private.

  2. Avoiding unwanted linkage between a claim issuer and receiver: Again I suggest 'signer' should not be mandatorily on-chain. Further, to avoid observation of the claims sent from 'a known claims issuer', it may be necessary to stipulate that a claim can only be received if it comes from a previously unused address (or the owning address). Since address pre-funding may also be an identifier, in future this would likely make use of 'contract pays' functionality.

Finally - can I check, would the handshake for authentication (receiving a challenge string, then signing and returning it) occur off chain (i.e. without introducing any new transactions into the blockchain), I think/hope this is the case, however at the London talk you mentioned the nightclub pays gas costs in this event. I would expect this to be an off-chain, zero-gas event. The alternative which I hope is not the case is that you are proposing each use of identity requires one or more tx's, which will introduce problems of scale, latency, cost, and most of all, privacy (all of which I think are avoidable for most usage scenarios)

Thanks for all the contributions and sorry for the delay, but the last 4 weeks were rather busy with devcon3 in the middle. I will try to address all the issues mentioned above.

@3esmit concerning a required approve ID:
This could certainly be also a bytes32, but i think a uint does the job as well, as it could be even prefixed with 10000000 or 2000000 for different approve types. E.g. key removal/additions vs executions or claim additions (10000000xxxx vs. 20000000xxxxx vs. 30000000xxx)
If bytes32 provide a cheaper way of determining the approval type we can switch.

**Concerning the #745 ** externalising the permissions could be a good idea, but would be also supported by the current draft as well, as you can set your approval to the 1 of 1 of a permission contract.
A standard is also just a suggestion not an eforcement.

One key could have multiple roles, but i wouldn't recommend that, as you don't want to loose your ACTION_KEY and then end up loosing your MANAGEMENT_KEY too which can lock you out. But an ACTION_KEY could also be a CLAIM_KEY. Which is see as less of a problem.

The addition of the keytype is a good idea. i will change that.

Yes actually we can return a boolean and give the execution ID in the event. But as of now no return values of transaction can be read anyway using the receipts, as they aren't contained in there.
The idea was that in the future we might add return values in the receipts and then it would be convenient.
If you want to check if a execution was successful you should look for the event Executed anyway.

Concerning the MUST in the execute, it should be SHOULD :) will change that.

@jarradh thank you so much for that!! I made the change above (adding uint256 _type to removeKey and replaceKey) could you add that?

@supertyler thanks for your comments.
Yes the standard should work for everything which can be identified. I will add organisations to the abstract.

Concerning key loss: Only one or multiple MANAGEMENT_KEYs could add or remove keys, action keys shouldn't, as these are the ones you carry around in your daily live. Also MANAGEMENT_KEYs could be a multisig of your council/family members, so that access loss is even impossible (as long as they don't loose theirs :) )
Freezing could happen when all action keys are removed.

About the negative claims. This is one of the key aspects of a self sovereign identity, that YOU are in control of it and you determine what goes on there. If a system for negative claims is needed this can be easily build as an external reputation system with different rules, or have registries for that. But if everybody can just add claims you have no control and there is no point of having a self controlled identity in the first place.
Though you can always add more functionality and a whitelist of claim issues who go on without approval without being incompatible with this standard. Ultimately what counts is the interface and events to make this standard compatible with UIs and other smart contracts, there can be all kind of extra functionality.
If the current spec is to strict we should loosen it to make it as flexible as possible.

Concerning privacy This is a good point. I see it as follows:
If certain claims could lead to a privacy issue, there could be claim issuer aggregators which groups certain claim types. E.g. if you don't want anybody to know that you are a UK citizen, instead of accepting a claim from the UK government that they have your biometric data, you can choose to use one of newly created aggregator services, which are trusted (or ideally trustless) which claim that they have a claim from somebody that you have biometric data, and that they can route to the data storage securely if needed (or provide proof if you send biometric data points, like scanned eyes or fingers)

The need for the claim data structure is to allow on chain verification, yes.

But one of the claims can easily be pointing to your secrets claim storage via a merkle hash, which can be a DID JSON structure.
So this standard allows for secrect as well as public claims, as well as public links. But ultimately it depends on the person or organisation of what he wants to be public.

I suggest also seeing this standard as less serious, Maybe my identity will be just a gamer profile, where i do want things to be public about me, and games and leagues to give me claims which are fully open.
Or people do want to link their linkedin, or facebook via claims.

For all more long lasting claims which you want to be secret, off chain claim storages are the only solution currently. Maybe in the future this can be replaced by zero knowledge proof contracts.

Concerning GDPR, which is a good move the user gets all the control of what to put and what to remove, though the right to be forgotten is certainly not something the blockchain can provide. And these laws were made in the context of other holding and controlling our user data to force them to "really" delete data on request. This law will still be needed for claim issuer, as they will keep the actual verified data. The blockchain identity acts only as the reference pointer.

Concerning spam This is something the blockchain itself deals with due to the cost of transactions, but we could certainly set a limit of stored claim requests, maybe it will pop out the oldest one when a new one comes in. But i am not sure if that needs to be standardised. It can be suggested in the spec though.

Concerning upgradeability This is something which can be part of the contract (upgradeable contract), but you could also move to a new identity and link your old one, or go to the claim issuer again and ask for new claims to be attached to the new one. But also this doesn't need to be part of the standard.
If we are talking about upgrading the standard itself, i would assume there will be a future standard which supersedes this one at one point.

@naddison36 this is an interesting idea, but i am not sure if thats needed on chain. In most cases you probably know which claim type and issuer you require to authenticate somebody. I wouldn't see a use case right now where you don't know the type and issuer but still want to put verify. But certainly something to be discussed.

@supertyler To the last comments:
There is a use case for fully public and publicly linked claims, so it needs at least the structure i suggest above. But it probably shouldn't be mandatory, so then a claimType 10 could be secretClaims, which has no signer, but links to the encrypted datastore and the root hash of the storage. Or there are multiple storages. Issuer here could be yourself.

Though i see we have a problem here, as we can't have multiple claims with the same claimType and issuer. So either we would change the claim index structure, or allow subtypes through claimType high number prefixes 1000001 and 1000002 ...

Thanks for all the discussion and please keep in mind this standard can be used for serious and less serious cases (.e.g. gamer identity vs. real idenity). So we have to find a standard which is flexible enough to cover both.

@supertyler yes, you can get the claim type but that is just an integer. How would someone checking a claim know what claim type 34543 is? And what if the claimant changes what they think claim type 34543 is? My preference is to have an immutable record of what the claim types are.

@frozenman thanks for the answer.
I think, as we are adding the key type to all add, replace and remove key, we can let MANAGEMENT_KEY account also be ACTOR_KEY or other, as on removeal we would need to set the type aswell.
For the replace would be interesting to not have type, instead move all keys in that acount to other account, or doing that when type is set to zero at replace.. Addkey and remove key type zero should error.

I see that using bytes32 in approval would be easier than checking arbitrary limited ranges in uint256, while in approval you need to check only which mapping contains that bytes32 value.
Anyway, the best practice in programming is to one function do specifically one thing, and approving transactions is a completely different thing then approving a claim.
I would find better to have a approveClaim in the ERC735 standard, then using the approve from ERC725 to ERC735 claims.

ERC745 can be used with this pattern yes, but having an approve method signature in ERC725 makes it looks like the code should be implemented at 725. And then if there some Identity using 745 some UI (like Mist) would not know what to do.

@alexvandesande for not having the approval in 725, the UI does not have to understand about approval regarding the identity, but only about reading the details about the Identity (such as management and actor key list);
Usually human-individual-identities will use an externally owned account to interface with their identity, because they don't want to need the call of other to sign it (Most identites will be for persons), although paranoid users might want to use multiple signatures which is generally good for security.

The way UI will deal with it is user that want a MultiSig Permission would add (or create it through Mist) the Permission Contracts which their EOA are owner and included in the Actor Key list of Identity. Then is just like the Multisig Wallet by Foundation that is supported by Mist will look like, btw, it could be a Multisig Wallet.
The UI would be able to understand the approval request coming from that MultiSig and also understand that it goes to that Identity, so, it would build a nice UI explaining what user is authorizing.
This also would give UI a better understanding, while it could understand several of permission contract classes such as a "dead man switch" or "friends recovery" or "authority-based e-mail/sms recovering", etc. having custom build UIs for each class.

Pardon my noob question but how will this ECR evolve to an EIP and actually be coded. Will the result of this be a Solidity library? Does it need to be approved by someone, or once the dialog has settled, coding begins. Do you have a rough timeline?

Excellent work by the way. I am excited by where this ECR is going.

A provable identity provided by Ethereum would be very useful for projects such as commento, obliviating the need for central autorities for single signon! Consider me intrigued …

@frozeman what do you think about multi-identity? Looks like we implemented this idea in a common way recently: https://github.com/bitclave/Multiownable

commented

While I applaud the effort, I have a few observations:

  1. the Identity API proposed here, is very much Ethereum-tailored, hence my concern would be regarding the universally accepted Identity API.
  2. How does this work relate to uPort and other Identity efforts? Are the companies like uPort, ShoCard, BlockAuth, ObjectTech, and so on, involved in the effort?

@3esmit what you mean with "move keys to the other account"?

I would suggest not using the ACTOR key as MANAGEMENT key, to improve security, but when a key management contract is used, it could be one address, certainly.

I dont understand the bytes32, vs uint256, could you give an example? Whats the benefit, as i can also have a mapping with utint256 values.

Concerning the multiple approve functions: This is certainly an interesting idea, but i deemed it better to reduce the amount of functions and leave the logic to the approve function internally to figure out which operation to approve.

@k06a this looks interesting and if it solves the approve process in a clean and simple way, we could certainly use that. Though i didn't look at the details yet, could you write which functions need to be ported? And this could certainly another standard, where then #725 is build using these separate standards.

@gregorypro The smart contract is running on the Ethereum based blockchain, so it is in some way ethereum related. BUT i fully agree that it should be gerneric enough to work as reference all kind of off chain and other chain projects. Therefore i already added the signatureType to the claim structure to allow multiple type of keys. And we should certainly do the same for the keys itself. E.g. making keys a struct as follows:

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

Concerning the other parties. I am in talks with uport and others, but ultimately this discussion is about a standard every of those projects can use, when they see there is a broad consensus. Systems which use commonly accepted standards win ultimately, so it will be up to them to contribute or come with a better standard.

@frozeman
I think I'm missing something here then, can you show me how I should fit the return of addClaim of #735 in approve defined by #725?

I see that 735 specifies:

function addClaim(uint256 _claimType, address issuer, uint256 signatureType, bytes _signature, bytes _data, string _uri) returns (bytes32 claimRequestId)

It returns (bytes32 claimRequestId)

while execute:

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

it returns (uint256 executionId);

See, they are uncompatible.
For me it's obvious how to approve execute using

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

But how to do it fo the bytes32 claimRequestId?

Should I convert the bytes32 to uint256?

ok. im want it))) its good idea. thx

@3esmit thats a mistake on my side then. It should be uint256, as the event below is also uint256, i mixed the up between the claimID and the claimRequestId.

I corrected it.

Small typo. The description of addKey needs to be uptaded to reflect the greater number of key types now enumerated:

addKey
Adds a _key to the identity. The _type specifies the type of key. Initially we propose two types:

addKey
Adds a _key to the identity. The _type specifies the type of key. Initially we propose four types:

IMPORTANT CHANGE

After speaking with @chriseth concerning multiple key types i made the following changes to the spec, to be discussed:

added getKey to return all the keys values (purpose, type, key)
getKeyType -> getKeyPurpose and requires bytes32 as argument.
getKeysByType -> getKeysByPurpose and returns array fo bytes32
addKey(bytes32 _key, uint256 _purpose, uint256 _type) etc. will receive a key in bytes32 format and also the type, while the old type is now purpose.
Also getKeyPurpose will return an array, as there could be one key having multiple purposes.

I removed replaceKey for now, as its more of a convenient function and with these new 3 requires parameters, not short anymore.

There are also changed to #735 in the claim structure, in so far that signatureType is changed for scheme. A scheme number will determine how the claim can be validated, e.g. scheme number 25 could mean that data is a function call, and issuer a contract address.
It can also have the meaning of a specific type of signature, or a specific way of how the actual claim data can be checked.

Thanks, this changes makes lots of sense, especially for the new uses of off-chain technologies.
Maybe I missed something but I would like to understand in the new design how we define a key that is another contract?
I see that we can have a type specifically for handling this that would not use a signature, instead the address of msg.sender as valid signature, but then I think we should define this important case in the ERC, and probably should be the first type - and this case could be allowed to be used by externally owned accounts or require msg.sender codesize > 0?

@frozeman @tjayrush I am the co-founder of The Humanized Internet and similarly we are looking at various scenarios working with the UN etc. Part of our team is someone who went through several of those scanarios and can speak to them. Scenarios include being A) captured and ability not to reveal real identity B) little to no smartphone penetration (slums and refugees) how do you capture an identity best ie fingerprint, facial recognition etc. C) Safety concerns with the UN is what data do we store and how do we make it bullet proof as history has shown us data revealed about people (whether color, religion) can and will be used in hardful ways. Food or thought and more than happy to discuss. Skype: mkovar01 or Cell (whatapp): 416-726-6746 . www.thehumanizedinternet.org

@mkovarsk I think this (protecting people from unscrupulous uses of this new "Identity-tech") is a super-important issue. I don't know how to help, but I support your efforts.

They got their proof - without that they need to actually see the biometric data, nor the address, as they trust the issuer - and they can proceed in opening an account.
#725 (comment)

This opens upp for the possiblitity of proving something about an account with a zkp without revelaing which identity owns that account.

As @oed said you could trustlessly use ZK-S(N/T)ARKs rather than trusting a claim issuer, which is important for Ethereum's decentralization ethos.

a.I would suggest a logic that permits explicit approval of claim by issuer - perhaps requiring an asynchronous process.
@overdrev, all processes that operate via the internet (and by extension, most blockchains), need to be asynchronous.

Another thing we have though a lot about is the privacy of claims. Right now there is basically no privacy for claims that are on-chain, which is basically a no-go for a lot of our use cases.

@oed, with ZK-S(T/N)ARKs you can keep private ID on-chain while using it, but not disclosing it, e.g. one's physical address, biometrics, or things that can count toward KYC ID, e.g. debit cards, letters from institutions with your name and address, government issued ID cards, etc.

@frozeman, @Arachnid, @bneiluj I don't think it's necessary to limit keys to meaning a cryptographic key just because the word is in code. If this becomes a frequent concern then it could be changed to id_key, however I believe that the ERC has been updated to define what a key is, I don't think it's necessary to do this.

> @overdrev I’m not sure if a Claim permission process is needed, except when an entity wants to know the details of the claim, e.g. see the biometric data stored by the issuer. Then of course we need a async process. I have made some thoughts about that, but this is not really part of this ERC and can be a separate standard.
I see it as follows: claim data (referenced by ‘bytes claim’) is double encrypted by the issuer and me, if somebody wants to see the actual data they request it at the issuers ‘bytes _location’ and request the issuers part to be decrypted, then they come to me and ask for decrypting the second part, which i can always decline.

b. Do we cover a single usage access method such that a third party can prove my info, but only once.

I think concerns like this are made redundant with ZK-S(T/N)ARKs. You don't need to disclose the ID to prove it, and why would you need to if the ZK-S(T/N)ARK proves the identity claim is correct? The proof only needs to be done once.

> Concerning privacy: as the claim data is only meta data, the only viable information one can retrieve from your identity is: which claim issuer has claims about me (e.g. the German state, or Vitalik claims something about me), and when that data has changed.

@frozeman, it's best to avoid leaking any data, including meta data. I think you really need to ensure privacy, in order to avoid manipulation of identity, e.g. with identity fraud. It's also important to have one identity per entity, in order to prevent Sybil attacks.

As i see it this standard is good for your public profile, meaning the things you want people to be able to access and proof about yourself. Like we fill pages on linkedin with quite personal data, to display our experience.

If you want to have private claims, they can always be in a private (encrypted?) claim storage based on DIDs, which can actually be linked as one of your claims (So they perfectly fit in this standard as well)

So this allows for public and private data, and its up to you what you put where.

What this standard mainly solves is the root problem. Where do i go look for somebodies data. Or from where i can find all the other places (which could be access restricted).

Concerning the meta data, as i already wrote (i think), there will be claim issuer aggregator services poping up, which then obfuscate from which country you are etc, as they proof your residency, or biometric data, but do this globally for many people/entities.

Obviously the best way would be to have zksnark proofs linked in claims, which can be auto-verified without revealing anything.

The nice things is that this standard "container" allows for all of that together and it doesn't restrict what you put in the claims. Though we need to define claim schemes so the verification process is clear. See my additions in #735

Here is the latest interface for this ERC

pragma solidity ^0.4.18;

contract ERC725 {

    uint256 constant MANAGEMENT_KEY = 1;
    uint256 constant ACTION_KEY = 2;
    uint256 constant CLAIM_SIGNER_KEY = 3;
    uint256 constant ENCRYPTION_KEY = 4;

    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);

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

    function getKey(bytes32 _key, uint256 _purpose) public constant returns(uint256 purpose, uint256 keyType, bytes32 key);
    function getKeyPurpose(bytes32 _key) public constant returns(uint256[] purpose);
    function getKeysByPurpose(uint256 _purpose) public constant returns(bytes32[] keys);
    function addKey(bytes32 _key, uint256 _purpose, uint256 _type) public returns (bool success);
    function execute(address _to, uint256 _value, bytes _data) public returns (uint256 executionId);
    function approve(uint256 _id, bool _approve) public returns (bool success);
}

Thanks will add this to the ERC above

i changed type to keyType. But i would actually like to rename that to type again, any ideas on that? Is there a case where it could conflict with soldities namespaces?

@frozeman In ERC735 you have "scheme" for the type of the key:

scheme: The scheme with which this claim SHOULD be verified or how it should be processed. Its a uint256 for different schemes. E.g. could 3 mean contract verification, where the data will be call data, and the issuer a contract address to call (ToBeDefined). Those can also mean different key types e.g. 1 = ECDSA, 2 = RSA, etc. (ToBeDefined)

@frozeman can you confirm keyType = 0 is used for contract calls as signature?

If now keys are able to be present with multiple purposes (inferring that from the fact that method getKeyPurpose returns an array), I would suggest renaming to plural getKeyPurposes.

@cbruguera on the same note, shouldn't the Key struct contain uint256[] purposes instead of just uint256?

Is there a case where new purposes can be added or selectively removed - isn't it simpler to remove the key completely and add it again just with new set of purposes?
If it isn't justifiable, I would propose to change the uint256 purpose into uint256[] purposes in general across the contact.

EDIT1:
Also, I don't think the same keys with different purposes should differ in type =>
function getKey(bytes32 _key, uint256 _purpose)
could be changed just to
function getKey(bytes32 _key)

Again, is there a case for multiple types on the same key?

EDIT2:
@tbocek @frozeman
I think the function removeKey() is missing from the interface.
function removeKey(bytes32 _key, uint256 purpose) public returns (bool success);
respectively:
function removeKey(bytes32 _key) public returns (bool success);

I tried to naively implement the key and execution handling https://github.com/JosefJ/IdentityContract/blob/master/contracts/KeyHolder.sol
The contract deviates from the so far stated description a bit as I applied some changes suggested in my last comment above.

The idea was that you can get one key per purpose. Using getKey(key, purpose) you can know if the key exists. This key should then only return that one purpose. To get all the keys purposes there is the extra function getKeyPurposes. Otherwise one could say you dont need to getKeyPurposes function at all, if the getKey gives you all purposes directly.

My idea was that smart contracts can simply determine with one call, if key X of purpose Y exists. Which is needed when you verify a claim, and checking the key and its purpose on the claim issuer.

Actually now reading @cbruguera comment again. The idea of getKeyPurpose() was to check if a key exists for a specific purpose.

We should think about a clean way to check that a key exists for a purpose, and having purposes returning an array, makes that tricky, as the smart contract would need to get the key and then check if the purpose is in the array, which is more costly. I would like to have one function to call for that.

@JosefJ testing your code, i dont seem to be able to get the key added in the constructor:
In remix:
"call to KeyHolder.getKey errored: VM error: revert.
revert The transaction has been reverted to the initial state.
Note: The constructor should be payable if you send value. Debug the transaction to get more information. "