-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Address metadata registry #926
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
## Preamble | ||
|
||
EIP: <to be assigned> | ||
Title: Address metadata registry | ||
Author: Nick Johnson <nick@ethereum.org> | ||
Type: Standard track | ||
Category: ERC | ||
Status: Draft | ||
Created: 2018-03-12 | ||
|
||
## Abstract | ||
This EIP specifies a registry for address metadata, permitting both contracts and external accounts to supply metadata about themselves to onchain and offchain callers. This permits use-cases such as generalised authorisations, providing token acceptance settings, and claims registries. | ||
|
||
## Motivation | ||
An increasing set of use cases require storage of metadata associated with an address; see for instance EIP 777 and EIP 780, and the ENS reverse registry in EIP 181. Presently each use-case defines its own specialised registry. To prevent a proliferation of special-purpose registry contracts, we instead propose a single standardised registry using an extendable architecture that allows future standards to implement their own metadata standards. | ||
|
||
## Specification | ||
The metadata registry has the following interface: | ||
``` | ||
interface AddressMetadataRegistry { | ||
function provider(address target) view returns(address); | ||
function setProvider(address _provider); | ||
} | ||
``` | ||
|
||
`setProvider` specifies the metadata registry to be associated with the caller's address, while `provider` returns the address of the metadata registry for the supplied address. | ||
|
||
The metadata registry will be compiled with an agreed-upon version of Solidity and deployed using the trustless deployment mechanism to a fixed address that can be replicated across all chains. | ||
|
||
## Provider specification | ||
|
||
Providers may implement any subset of the metadata record types specified here. Where a record types specification requires a provider to provide multiple functions, the provider MUST implement either all or none of them. Providers MUST throw if called with an unsupported function ID. | ||
|
||
Providers have one mandatory function: | ||
|
||
``` | ||
function supportsInterface(bytes4 interfaceID) constant returns (bool) | ||
``` | ||
|
||
The `supportsInterface` function is documented in [EIP 165](https://github.com/ethereum/EIPs/issues/165), and returns true if the provider implements the interface specified by the provided 4 byte identifier. An interface identifier consists of the XOR of the function signature hashes of the functions provided by that interface; in the degenerate case of single-function interfaces, it is simply equal to the signature hash of that function. If a provider returns `true` for `supportsInterface()`, it must implement the functions specified in that interface. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the motivation behind using XOR of the signature IDs rather than a hash of all of the signatures? While I suspect someone can implement the XOR without too much difficulty, keccak hashing of things in the Solidity ecosystem is a well understood problem as it is used everywhere while XOR of first 4 bytes of a keccak hash of a thing is significantly less understood by the average developer. The following is what the hash might look like, which is pretty familiar to any Ethereum developer at this point and can be done in Solidity or in JavaScript (most common dapp development language).
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See EIP 165 for justification. I don't think this is a good place to rehash that. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Glanced through that, there was a reference to a Gitter conversation where Was there a particular comment that you feel captures the argument over there? It is possible I missed a subtle argument as I was skimming the comments rather than analyzing them in depth. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I really don't want to get derailed on arguing the merits of an unrelated standard in this EIP. Can you open a discussion on 165 instead? It's unlikely we can make a change at this point, though, since it's already widely deployed (eg, on ENS for one). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, now that I have read EIP 165 and realize that this section is just a watered down summary of 165 I no longer want to press the bytes32 vs XOR thing here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should link to the draft of EIP 165, not the issue: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After reading EIP 165 (draft rather than the GitHub issue, which was much harder to follow), I am now confused why this entire section exists. It appears to just be re-hashing what EIP 165 says, but with less context, less detail and fewer examples. Why not just say that providers are defined by EIP 165 and leave it at that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought a brief description would be useful so that someone who only wants to implement it doesn't need to read all of 165, too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I need to step away and think a bit more to avoid curve fitting my personal experience, but my gut right now is telling me that the fact that there was a bunch of text rather than just a link resulted in me ignoring the link and reading just the text, which unfortunately is lacking in the detail I would expect from an EIP. |
||
|
||
`supportsInterface` must always return true for `0x01ffc9a7`, which is the interface ID of `supportsInterface` itself. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the point of this? At first blush it feels like it is just a clever little thing to chuckle at in the spec, but not something that anyone would ever need for anything. I'm guessing the thought is that you can call this to check if Is there some other reason for this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, recommend changing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also see 165 and 137; the idea is that it lets a generic caller determine if the contract implements There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As mentioned over in #165 (and I didn't see a rebuttal, though I may have missed it) older Solidity (based on discussion there it sounds like this has since been fixed) contracts will return garbage data by default (meaning true or false). Thus if someone calls There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It appears that 165 addresses this problem with:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Only if they implement a fallback that doesn't throw - which this standard explicitly prohibits. |
||
|
||
The first argument to all provider functions MUST be the address being queried; this facilitates the creation of multi-user provider contracts. | ||
|
||
Currently standardised provider interfaces are specified in the table below. | ||
|
||
| Interface name | Interface hash | Specification | | ||
| --- | --- | --- | | ||
|
||
EIPs may define new interfaces to be added to this registry. | ||
|
||
## Rationale | ||
There are two obvious approaches for a generic metadata registry: the indirection approach employed here, or a generalised key/value store. While indirection incurs the cost of an additional contract call, and requires providers to change over time, it also provides for significantly enhanced flexibility over a key/value store; for that reason we selected this approach. | ||
|
||
## Backwards Compatibility | ||
There are no backwards compatibility concerns. | ||
|
||
## Implementation | ||
The canonical implementation of the metadata registry is as follows: | ||
``` | ||
contract AddressMetadataRegistry { | ||
mapping(address=>address) public provider; | ||
|
||
function setProvider(address _provider) { | ||
provider[msg.sender] = _provider; | ||
} | ||
} | ||
``` | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Recommend including an example provider as well that at least implements the required There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, though callers don't need to do the function hashing, just embed the appropriate constants (unless we can trust solidity to optimise those out, even if optimisation is turned off?) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there is value in showing a user how to do the XOR, hashing and byte chopping in code, and Solidity is the language that we can be certain all readers of these understand. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If Solidity doesn't optimise-away the hashing at compile-time, though, this is going to be a significant waste of gas. Edit: And in any case this is likely something that should be demoed in 165. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would be OK (though not quite as satisfied) with an example written in JS if you think that is more reasonable. Solidity is just the "common language". I would not recommend people actually do the hashing in Solidity with each contract call. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, I don't think this is the place to do it - this is just a user of EIP165; any examples should probably be there. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a developer who didn't know of EIP 165's prior to reading this EIP, I was surprised to find it lacking an example for the "other side". If you think this EIP should depend on 165, then I recommend including such a dependency in the EIP and indicating how the two are connected to each other. In general, if an EIP doesn't reference any other EIPs, then I assume it can be consumed on its own (which is what I tried to do when reading this EIP) and it seems that your intent is that this EIP is not consumed on its own. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And of course after saying that, I re-read this EIP and found it did mention EIP 165... |
||
|
||
## Copyright | ||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity, recommend including the Solidity code for this:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solidity implements this automatically now.