From 0f7c5e2d061cfe6cf22b7ae421f4f6b3a8da56dc Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:32:45 +0000 Subject: [PATCH 1/5] Add a section about the offchain storage service --- .../ensip-16-offchain-metadata.md | 46 +++++++++++++++++-- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/ens-improvement-proposals/ensip-16-offchain-metadata.md b/ens-improvement-proposals/ensip-16-offchain-metadata.md index 30f88abd..90e729ed 100644 --- a/ens-improvement-proposals/ensip-16-offchain-metadata.md +++ b/ens-improvement-proposals/ensip-16-offchain-metadata.md @@ -23,7 +23,7 @@ This ENSIP addresses this by adding a way of important metadata to be gathered o The metadata should include 2 different types of info -- Offchain data storage location related info: `graphqlUrl` includes the URL to fetch the metadata. +- Offchain data storage location related info: `graphqlUrl` includes the URL to fetch the metadata. - Ownership related info: `owner`, `isApprovedForAll` defines who can own or update the given record. @@ -63,7 +63,7 @@ interface IOffChainResolver { * @return coinType according to https://github.com/ensdomains/address-encoder * @return graphqlUrl url of graphql endpoint that provides additional information about the offchain name and its subdomains * @return storageType 0 = EVM, 1 = Non blockchain, 2 = Starknet - * @storageLocation = l2 contract address + * @storageLocation = When storageType is 0, l2 contract address. When storageType is 1, url endpoint in bytes format * @return context = an arbitrary bytes string to define the namespace to which a record belongs such as the name owner. */ function metadata(bytes calldata name) @@ -190,6 +190,46 @@ type Resolver @entity { } ``` +### Offchain storage service + +[EIP-5559](https://eips.ethereum.org/EIPS/eip-5559#data-stored-in-an-off-chain-database) has already been proposed to handle both L2 and off chain storage by utilizing the similar method to [EIP-3668](https://eips.ethereum.org/EIPS/eip-3668). +While this is technically feasible, it adds extra function calls simply to discover how to update the data. The simpler alternative for ENS related storage update is to query storage service endpoint from `storageLocation` in bytes format when `storateType` is set to `1`. The client then make a HTTP POST request to the storage location with signature information. + +The body attached to the request is a JSON object that includes sender, data, inception date and a signed copy of the abi encoded data, sender, and inception date. + +Example HTTP POST request body including requestParams and signature: + +``` + const name = 'vitalik.eth' + const node = ethers.utils.namehash(name) + const iface = new ethers.utils.Interface(['function setAddr(bytes,address)']) + const signer = signers[0] + const signerAddress = signer.address + const data = iface.encodeFunctionData('setAddr',[node, signerAddress]) + const block = await ethers.provider.getBlock('latest') + inceptionDate = block.timestamp + signature = await signers[0].signMessage( + ethers.utils.arrayify( + keccak256( + ['bytes', 'address', 'uint256'], + [ + data, + signer, + inceptionDate + ], + ), + ), + ) + const request = { + data:, + sender:signer, + inceptionDate, + signature + } +``` + +Once the storage service receives the request, it decodes the sender information from the signed signature and perform the data update if the `sender` matches the name onwer defined by the optional `context` field. + ### Backwards Compatibility None @@ -200,4 +240,4 @@ None ### Copyright -Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). \ No newline at end of file From 553465640d82502d4ab9ca64eeb4c9a548d25c40 Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:32:59 +0000 Subject: [PATCH 2/5] Remove owner --- ens-improvement-proposals/ensip-16-offchain-metadata.md | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/ens-improvement-proposals/ensip-16-offchain-metadata.md b/ens-improvement-proposals/ensip-16-offchain-metadata.md index 90e729ed..9e9aa056 100644 --- a/ens-improvement-proposals/ensip-16-offchain-metadata.md +++ b/ens-improvement-proposals/ensip-16-offchain-metadata.md @@ -47,18 +47,12 @@ By passing the name through metadata, we empower the resolution process, enablin // To be included in // https://github.com/ensdomains/ens-contracts/blob/staging/contracts/resolvers/Resolver.sol interface IOffChainResolver { - /** @dev Returns the owner of the resolver on L2 - * @param node - * @return owner in bytes32 instead of address to cater for non EVM based owner information - */ - owner(bytes32 node) returns (bytes owner); - // optional. // this returns data via l2 with EIP-3668 so that non EVM chains can also return information of which address can update the record // The same function name exists on L2 where delegate returns address instead of bytes function isApprovedFor(bytes context, bytes32 node, bytes delegate) returns (bool); - /** @dev Returns the owner of the resolver on L2 + /** @dev Returns the metadata about the node * @return name can be l2 chain name or url if offchain * @return coinType according to https://github.com/ensdomains/address-encoder * @return graphqlUrl url of graphql endpoint that provides additional information about the offchain name and its subdomains From 6aba96ca6b6d78490d85e115648f412a056e519a Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Tue, 6 Feb 2024 15:33:54 +0000 Subject: [PATCH 3/5] Remove signer from data --- ens-improvement-proposals/ensip-16-offchain-metadata.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ens-improvement-proposals/ensip-16-offchain-metadata.md b/ens-improvement-proposals/ensip-16-offchain-metadata.md index 9e9aa056..9fe0013a 100644 --- a/ens-improvement-proposals/ensip-16-offchain-metadata.md +++ b/ens-improvement-proposals/ensip-16-offchain-metadata.md @@ -205,10 +205,9 @@ Example HTTP POST request body including requestParams and signature: signature = await signers[0].signMessage( ethers.utils.arrayify( keccak256( - ['bytes', 'address', 'uint256'], + ['bytes', 'uint256'], [ data, - signer, inceptionDate ], ), From 1f82088916af48563625bb9bc7964abc1808bde4 Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Tue, 6 Feb 2024 16:00:37 +0000 Subject: [PATCH 4/5] Change from HTTP POST from JSON rpc request and use hasheddata --- .../ensip-16-offchain-metadata.md | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/ens-improvement-proposals/ensip-16-offchain-metadata.md b/ens-improvement-proposals/ensip-16-offchain-metadata.md index 9fe0013a..908b4f87 100644 --- a/ens-improvement-proposals/ensip-16-offchain-metadata.md +++ b/ens-improvement-proposals/ensip-16-offchain-metadata.md @@ -187,19 +187,20 @@ type Resolver @entity { ### Offchain storage service [EIP-5559](https://eips.ethereum.org/EIPS/eip-5559#data-stored-in-an-off-chain-database) has already been proposed to handle both L2 and off chain storage by utilizing the similar method to [EIP-3668](https://eips.ethereum.org/EIPS/eip-3668). -While this is technically feasible, it adds extra function calls simply to discover how to update the data. The simpler alternative for ENS related storage update is to query storage service endpoint from `storageLocation` in bytes format when `storateType` is set to `1`. The client then make a HTTP POST request to the storage location with signature information. +While this is technically feasible, it adds extra function calls simply to discover how to update the data. The simpler alternative for ENS related storage update is to query storage service endpoint from `storageLocation` in bytes format when `storateType` is set to `1`. The client then make a JSON RPC call to the storage location with signature information. The body attached to the request is a JSON object that includes sender, data, inception date and a signed copy of the abi encoded data, sender, and inception date. -Example HTTP POST request body including requestParams and signature: +Example JSON RPC request including requestParams and signature: ``` + const keccak256 = ethers.utils.solidityKeccak256 const name = 'vitalik.eth' const node = ethers.utils.namehash(name) const iface = new ethers.utils.Interface(['function setAddr(bytes,address)']) const signer = signers[0] const signerAddress = signer.address - const data = iface.encodeFunctionData('setAddr',[node, signerAddress]) + const hasheddata = keccak256(['bytes', 'address'], [node, address]) const block = await ethers.provider.getBlock('latest') inceptionDate = block.timestamp signature = await signers[0].signMessage( @@ -207,17 +208,24 @@ Example HTTP POST request body including requestParams and signature: keccak256( ['bytes', 'uint256'], [ - data, + hasheddata, inceptionDate ], ), ), ) +``` + +``` const request = { - data:, - sender:signer, - inceptionDate, - signature + "jsonrpc":"2.0", + "method":"ccipWrite", + params:{ + "data":data, + "sender":signer, + "inceptionDate":inceptionDate, + "signature":signature + } } ``` From 9827f3853e36eea899a4dffd2cdf5c4604ad3c16 Mon Sep 17 00:00:00 2001 From: Makoto Inoue <2630+makoto@users.noreply.github.com> Date: Thu, 8 Feb 2024 14:17:40 +0000 Subject: [PATCH 5/5] Change from json RPC back to HTTP POST --- .../ensip-16-offchain-metadata.md | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/ens-improvement-proposals/ensip-16-offchain-metadata.md b/ens-improvement-proposals/ensip-16-offchain-metadata.md index 908b4f87..8212441f 100644 --- a/ens-improvement-proposals/ensip-16-offchain-metadata.md +++ b/ens-improvement-proposals/ensip-16-offchain-metadata.md @@ -187,11 +187,11 @@ type Resolver @entity { ### Offchain storage service [EIP-5559](https://eips.ethereum.org/EIPS/eip-5559#data-stored-in-an-off-chain-database) has already been proposed to handle both L2 and off chain storage by utilizing the similar method to [EIP-3668](https://eips.ethereum.org/EIPS/eip-3668). -While this is technically feasible, it adds extra function calls simply to discover how to update the data. The simpler alternative for ENS related storage update is to query storage service endpoint from `storageLocation` in bytes format when `storateType` is set to `1`. The client then make a JSON RPC call to the storage location with signature information. +While this is technically feasible, it adds extra function calls simply to discover how to update the data. The simpler alternative for ENS related storage update is to query storage service endpoint from `storageLocation` in bytes format when `storateType` is set to `1`. The client then make a HTTP POST call to the storage location with signature information. The body attached to the request is a JSON object that includes sender, data, inception date and a signed copy of the abi encoded data, sender, and inception date. -Example JSON RPC request including requestParams and signature: +Example HTTP POST request including requestParams and signature: ``` const keccak256 = ethers.utils.solidityKeccak256 @@ -200,16 +200,17 @@ Example JSON RPC request including requestParams and signature: const iface = new ethers.utils.Interface(['function setAddr(bytes,address)']) const signer = signers[0] const signerAddress = signer.address - const hasheddata = keccak256(['bytes', 'address'], [node, address]) + const data = iface.encodeFunctionData('setAddr',[node, signerAddress]) + const hasheddata = keccak256(['bytes'], [data]) const block = await ethers.provider.getBlock('latest') - inceptionDate = block.timestamp + inception = block.timestamp signature = await signers[0].signMessage( ethers.utils.arrayify( keccak256( ['bytes', 'uint256'], [ hasheddata, - inceptionDate + inception ], ), ), @@ -218,14 +219,9 @@ Example JSON RPC request including requestParams and signature: ``` const request = { - "jsonrpc":"2.0", - "method":"ccipWrite", - params:{ - "data":data, - "sender":signer, - "inceptionDate":inceptionDate, - "signature":signature - } + data:, + inception, + signature } ```