Ethereum 2 wallet layout
Simple Summary
A standard layout and naming format for walletstore and keystore for both hierarchical (e.g. filesystem, Amazon S3) and non-hierarchical (key/value) storage systems.
Abstract
Ethereum wallets have no standards for their layout in persistent storage, making different wallet implementations incompatible. This defines a standard for the placement of Ethereum walletstores and keystores, making it possible for different software to work with the same wallets and keys.
Motivation
A standard layout for wallets and accounts allows interoperability between validators. This benefits users, as they can move from one validator software to another (and back) without requiring movement of files. This is important because any movement of files containing keys involves danger of either deleting them or duplicating them, both of which could cause loss of access to funds.
Specification
There are four elements for a wallet that need to be addressed. These are defined below.
Base location
The base location is required to be well-known, either pre-defined or defined by the storage system’s connection parameters.
For filesystems the pre-defined base location for different operating systems is as follows:
- Windows:
%APPDATA%\ethereum2\wallets
- MacOSX:
${HOME}/Library/Application Support/ethereum2/wallets
- Linux:
${HOME}/.config/ethereum2/wallets
For other hierarchical stores, for example Amazon S3, the base location MUST be the lower-case hex string representing the SHA-256 hash of the string “Ethereum 2 wallet:” appended with the identifier for the hierarchical store. For example, if the account ID for a user’s Amazon S3 account is “AbC0438EB” then:
- string would be
Ethereum 2 wallet:AbC0438EB
- SHA-256 hash of string would be the byte array
0x991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229
- base location would be the string
991ec14a8d13836b10d8c3039c9e30876491cb8aa9c9c16967578afc815c9229
For non-hierarchical stores there is no base location.
Wallet container
The wallet container holds the walletstore and related keystores.
The wallet container is identified by the wallet’s UUID. It MUST be a string following the syntactic structure as laid out in section 3 of RFC 4122.
Walletstore
The walletstore element contains the walletstore and is held within the wallet container. It is identified by the wallet’s UUID. It MUST be a string following the syntactic structure as laid out in section 3 of RFC 4122.
Keystore
The keystore element contains the keystore for a given key and is held within the wallet container. It is identified by the key’s UUID. It MUST be a string following the syntactic structure as laid out in section 3 of RFC 4122.
Hierarchical store example
Hierarchical stores are a common way to store and organize information. The most common example is the filesystem, but a number of object-based stores such as Amazon S3 also provide hierarchical naming.
Putting these elements together for a sample wallet with wallet UUID 1f031fff-c51d-44fc-8baf-d6b304cb70a7
and key UUIDs 1302106c-8441-4e2e-b687-6c77f49fc624
and 4a320100-83fd-4db7-8126-6d6d205ba834
gives the following layout:
- 1f031fff-c51d-44fc-8baf-d6b304cb70a7
+- 1302106c-8441-4e2e-b687-6c77f49fc624
+- 1f031fff-c51d-44fc-8baf-d6b304cb70a7
+- 4a320100-83fd-4db7-8126-6d6d205ba834
Non-hierarchical store example
Non-hierarchical stores use a simplified approach where the wallet UUID and key UUIDs are concatenated using the ‘:’ character. Using the same example wallet and key UUIDs as above would result in objects with the following keys:
1f031fff-c51d-44fc-8baf-d6b304cb70a7:1302106c-8441-4e2e-b687-6c77f49fc624
1f031fff-c51d-44fc-8baf-d6b304cb70a7:1f031fff-c51d-44fc-8baf-d6b304cb70a7
1f031fff-c51d-44fc-8baf-d6b304cb70a7:4a320100-83fd-4db7-8126-6d6d205ba834
Protecting against concurrent write access
TBD
Iterating over wallets
In the case of hierarchical stores and iteration-capable non-hierarchical stores iteration over wallets is a matter of iterating over the files in the root container.
An implementer MAY include an index in the base location. If so then it MUST follow the structure as specified in the following “Index format” section.
Iterating over accounts
In the case of hierarchical stores iteration over accounts is a matter of iterating over the files in the wallet container.
An implementer MAY include an index within a wallet container for accounts within that wallet. If so then it MUST follow the structure as specified in the following “Index format” section.
Index format
The index format is the same for both wallets and accounts, following a standard JSON schema.
{
"type": "array",
"items": {
"type": "object",
"properties": {
"uuid": {
"type": "string"
},
"name": {
"type": "string"
}
},
"required": [
"uuid",
"name"
]
}
}
The index MUST use the identifier ‘index’.
Public keys must NOT be stored in the index.
Rationale
A standard for walletstores, similar to that for keystores, provides a higher level of compatibility between wallets and allows for simpler wallet and key interchange between them.
Implementation
A Go implementation of the filesystem layout can be found at https://github.com/wealdtech/go-eth2-wallet-filesystem.
A Go implementation of the Amazon S3 layout can be found at https://github.com/wealdtech/go-eth2-wallet-s3.
Security Considerations
Locations for wallet stores are defined to be within each user’s personal space, reducing the possibility of accidental exposure of information. It is, however, still possible for permissions to be set such that this data is world-readable, and applications implementing this EIP should attempt to set, and reset, permissions to ensure that only the relevant user has access to the information.
The names for both wallet and key stores are UUIDs, ensuring that no data is leaked from the metadata.
Copyright
Copyright and related rights waived via CC0.