Organizational metadata: Strategy for using custom resolver

In the latest iteration of our technical design for the organizational metadata project, we are thinking there should be two kinds of metadata that can be attached to an ENS name/subname:

  1. A required classification, which explains the node’s role in the organizational structure. Values could include things like wallet, person, or contract.
  2. Optional attributes that belong to this entity, which would be situational. For example, a basic wallet classification would not have any additional attributes, but a person entity could have attributes such as name, email address, etc.

We want adoption of this system to be as frictionless as possible, so the current plan is to add the classification as a text record. This would allow users with existing registrations on the public resolver to simply add a text record to each entry to classify all the nodes in the data tree that is their ENS name. This could even be done by hand through the current ENS UI.

However, attributes can be quite numerous, and adding them as text records would get complicated quite quickly. For one, the key of each would need to be standardized based on the classification of the node. This would require implementers to know which key names are valid and to name them correctly.

Additionally, a node can have its class changed by simply updating the classification text record to a different type. However if the entry still had a bunch of text records containing attributes of the old type, that would be very confusing and could be hard to clean up.

Therefore, a much more elegant solution would be to introduce a metadata resolver which enforces data structures for this system. It could, for example, store validated structs of attributes based on the classification of the node, and if the classification were to change those structs could be deleted/updated automatically.

My question for this thread is about frictionless onboarding to promote adoption.

If we were to introduce a new resolver, it could have a class(node) method which returns the classification, instead of relying on text(node, metadata-key) from the current resolver. However, I feel we would not see much adoption from existing users if they were required to switch resolver and repopulate their records for every node they already have registered.

I think the best solution could be thus:

  1. The spec will specify that consumers should first query the interface of the resolver, and if it is a metadata resolver they should call class(node) to get the classification. Otherwise, they should call text(node, metadata-key) to see if a classification is set, as a fallback.
  2. If users want to set a classification, they can either use the current resolver with a text record or use the new resolver.
  3. If users want to add attributes to a node, they must use the new resolver (and not even support adding attributes as regular text records)

This would allow people to start using the system frictionlessly with the existing setups, and allow them to upgrade for better functionality when they are ready.

Does this sound like the right approach? And looking further forward, would this perhaps be a good way to introduce new resolvers in the future? We could establish a precedent where new functionality uses text records to start, and then migrates to a custom resolver when adoption grows (but the names of the text records would probably need to be reserved permanently for legacy support).

1 Like

I think this adds unnecesary complexity; it also means that users have to switch resolvers to use the protocol.

Why not instead use ENSIP-24 and specify a standard compact format using, say, CBOR or Protocol Buffers, for encoding all of this metadata in a single binary record?

1 Like

This is cool. Will investigate with @clowes.eth further.

Thanks for bringing this to our attention. Just got back from Edge/DevCon so still catching up on what we missed in the past 6 weeks.

1 Like

Thanks for these suggestions. Basically, there are three options we have considered:

  1. Use separate text records for each metadata attribute.
  2. Use one unstructured-data record to store all attributes encoded together.
  3. Use a custom resolver or other solution to store structured data for each node.

The 3rd solution (which I proposed above) moves all of the validation and storage optimizations on-chain, whereas solution 2 leaves that onus on the user. Solution 2 also has the downside of needing to rewrite the entire record even if you just want to change the value of one single attribute.

But I agree with you that the simplicity of number 2 is probably worth the tradeoffs!

Unless I’m missing something:

For classification the existing text records capability of resolvers seems like a good fit.

For a list of any number of attributes, this could also be achieved through the existing text records capability of resolvers, where the value for an attribute could be defined to follow a defined formatting which could be JSON or one of any number of other options.

Don’t recommend requiring new custom resolvers if you hope to see adoption.

JSON is quite verbose by onchain standards, however. Given there’s already an open spec for binary records, this seems like an obvious use case for them.

1 Like

Thanks for helping me think this through!

I was trying to find the best compromise between convenience for developers and data efficiency.

Just throwing JSON into records is easy and convenient, but JSON is very redundant and inefficient if the data always follows a known structure.

Optimizing the storage by converting attribute names to byte codes would be efficient, but would be a pain for developers to implement and hard to debug.

Relying on contracts to store structured data would be fool-proof for developers and efficient, but adoption would suffer.

TL;DR: I really like the idea of storing CBOR in existing text/bytes records. The attribute names can be short, but still human-readable, and we can deploy on-chain helper contracts that take structured data and properly encode and update records to keep it easy for developers. This is the new plan.

1 Like