From dc4c40414e6fb76d3c56aa771752dd6ade61c280 Mon Sep 17 00:00:00 2001 From: pldespaigne Date: Thu, 4 Apr 2019 17:15:57 +0200 Subject: issue#5742 --- app/scripts/lib/ens-ipfs/contracts/resolver.js | 2 +- app/scripts/lib/ens-ipfs/resolver.js | 30 ++++++++++++++------- app/scripts/lib/ens-ipfs/setup.js | 36 +++++++++++++++----------- 3 files changed, 42 insertions(+), 26 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/ens-ipfs/contracts/resolver.js b/app/scripts/lib/ens-ipfs/contracts/resolver.js index 1bf3f90ce..b61fbed88 100644 --- a/app/scripts/lib/ens-ipfs/contracts/resolver.js +++ b/app/scripts/lib/ens-ipfs/contracts/resolver.js @@ -1,2 +1,2 @@ module.exports = -[{'constant': true, 'inputs': [{'name': 'interfaceID', 'type': 'bytes4'}], 'name': 'supportsInterface', 'outputs': [{'name': '', 'type': 'bool'}], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'contentTypes', 'type': 'uint256'}], 'name': 'ABI', 'outputs': [{'name': 'contentType', 'type': 'uint256'}, {'name': 'data', 'type': 'bytes'}], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'x', 'type': 'bytes32'}, {'name': 'y', 'type': 'bytes32'}], 'name': 'setPubkey', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'content', 'outputs': [{'name': 'ret', 'type': 'bytes32'}], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'addr', 'outputs': [{'name': 'ret', 'type': 'address'}], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'contentType', 'type': 'uint256'}, {'name': 'data', 'type': 'bytes'}], 'name': 'setABI', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'name', 'outputs': [{'name': 'ret', 'type': 'string'}], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'name', 'type': 'string'}], 'name': 'setName', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'hash', 'type': 'bytes32'}], 'name': 'setContent', 'outputs': [], 'payable': false, 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'pubkey', 'outputs': [{'name': 'x', 'type': 'bytes32'}, {'name': 'y', 'type': 'bytes32'}], 'payable': false, 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'addr', 'type': 'address'}], 'name': 'setAddr', 'outputs': [], 'payable': false, 'type': 'function'}, {'inputs': [{'name': 'ensAddr', 'type': 'address'}], 'payable': false, 'type': 'constructor'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'a', 'type': 'address'}], 'name': 'AddrChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'hash', 'type': 'bytes32'}], 'name': 'ContentChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'name', 'type': 'string'}], 'name': 'NameChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': true, 'name': 'contentType', 'type': 'uint256'}], 'name': 'ABIChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'x', 'type': 'bytes32'}, {'indexed': false, 'name': 'y', 'type': 'bytes32'}], 'name': 'PubkeyChanged', 'type': 'event'}] +[{'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'hash', 'type': 'bytes32'}], 'name': 'setContent', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'content', 'outputs': [{'name': '', 'type': 'bytes32'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'interfaceID', 'type': 'bytes4'}], 'name': 'supportsInterface', 'outputs': [{'name': '', 'type': 'bool'}], 'payable': false, 'stateMutability': 'pure', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'key', 'type': 'string'}, {'name': 'value', 'type': 'string'}], 'name': 'setText', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'contentTypes', 'type': 'uint256'}], 'name': 'ABI', 'outputs': [{'name': 'contentType', 'type': 'uint256'}, {'name': 'data', 'type': 'bytes'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'x', 'type': 'bytes32'}, {'name': 'y', 'type': 'bytes32'}], 'name': 'setPubkey', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'hash', 'type': 'bytes'}], 'name': 'setContenthash', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'addr', 'outputs': [{'name': '', 'type': 'address'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'key', 'type': 'string'}], 'name': 'text', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'contentType', 'type': 'uint256'}, {'name': 'data', 'type': 'bytes'}], 'name': 'setABI', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'name', 'outputs': [{'name': '', 'type': 'string'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'name', 'type': 'string'}], 'name': 'setName', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'contenthash', 'outputs': [{'name': '', 'type': 'bytes'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': true, 'inputs': [{'name': 'node', 'type': 'bytes32'}], 'name': 'pubkey', 'outputs': [{'name': 'x', 'type': 'bytes32'}, {'name': 'y', 'type': 'bytes32'}], 'payable': false, 'stateMutability': 'view', 'type': 'function'}, {'constant': false, 'inputs': [{'name': 'node', 'type': 'bytes32'}, {'name': 'addr', 'type': 'address'}], 'name': 'setAddr', 'outputs': [], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'function'}, {'inputs': [{'name': 'ensAddr', 'type': 'address'}], 'payable': false, 'stateMutability': 'nonpayable', 'type': 'constructor'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'a', 'type': 'address'}], 'name': 'AddrChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'name', 'type': 'string'}], 'name': 'NameChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': true, 'name': 'contentType', 'type': 'uint256'}], 'name': 'ABIChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'x', 'type': 'bytes32'}, {'indexed': false, 'name': 'y', 'type': 'bytes32'}], 'name': 'PubkeyChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'indexedKey', 'type': 'string'}, {'indexed': false, 'name': 'key', 'type': 'string'}], 'name': 'TextChanged', 'type': 'event'}, {'anonymous': false, 'inputs': [{'indexed': true, 'name': 'node', 'type': 'bytes32'}, {'indexed': false, 'name': 'hash', 'type': 'bytes'}], 'name': 'ContenthashChanged', 'type': 'event'}] diff --git a/app/scripts/lib/ens-ipfs/resolver.js b/app/scripts/lib/ens-ipfs/resolver.js index 18f7704c3..3f0fb00a2 100644 --- a/app/scripts/lib/ens-ipfs/resolver.js +++ b/app/scripts/lib/ens-ipfs/resolver.js @@ -1,9 +1,9 @@ const namehash = require('eth-ens-namehash') -const multihash = require('multihashes') const Eth = require('ethjs-query') const EthContract = require('ethjs-contract') const registryAbi = require('./contracts/registry') const resolverAbi = require('./contracts/resolver') +const contentHash = require('content-hash') module.exports = resolveEnsToIpfsContentId @@ -26,16 +26,26 @@ async function resolveEnsToIpfsContentId ({ provider, name }) { throw new Error(`EnsIpfsResolver - no resolver found for name "${name}"`) } const Resolver = contract(resolverAbi).at(resolverAddress) - // lookup content id - const contentLookupResult = await Resolver.content(hash) - const contentHash = contentLookupResult[0] - if (hexValueIsEmpty(contentHash)) { - throw new Error(`EnsIpfsResolver - no content ID found for name "${name}"`) + + const isEIP1577Compliant = await Resolver.supportsInterface('0xbc1c58d1') + const isLegacyResolver = await Resolver.supportsInterface('0xd8389dc5') + if (isEIP1577Compliant[0]) { + const contentLookupResult = await Resolver.contenthash(hash) + const rawContentHash = contentLookupResult[0] + const decodedContentHash = contentHash.decode(rawContentHash) + const type = contentHash.getCodec(rawContentHash) + return {type: type, hash: decodedContentHash} + } + if (isLegacyResolver[0]) { + // lookup content id + const contentLookupResult = await Resolver.content(hash) + const content = contentLookupResult[0] + if (hexValueIsEmpty(content)) { + throw new Error(`EnsIpfsResolver - no content ID found for name "${name}"`) + } + return {type: 'swarm-ns', hash: content.slice(2)} } - const nonPrefixedHex = contentHash.slice(2) - const buffer = multihash.fromHexString(nonPrefixedHex) - const contentId = multihash.toB58String(multihash.encode(buffer, 'sha2-256')) - return contentId + throw new Error(`EnsIpfsResolver - the resolver for name "${name}" is not standard, it should either supports contenthash() or content()`) } function hexValueIsEmpty (value) { diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index df756d0f7..43194afbd 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -38,23 +38,29 @@ function setupEnsIpfsResolver ({ provider }) { async function attemptResolve ({ tabId, name, path, search }) { extension.tabs.update(tabId, { url: `loading.html` }) try { - const ipfsContentId = await resolveEnsToIpfsContentId({ provider, name }) - const url = `https://gateway.ipfs.io/ipfs/${ipfsContentId}${path}${search || ''}` - try { - // check if ipfs gateway has result - const response = await fetch(url, { method: 'HEAD' }) - // if failure, redirect to 404 page - if (response.status !== 200) { - extension.tabs.update(tabId, { url: '404.html' }) - return + let url = '400.html' + const {type, hash} = await resolveEnsToIpfsContentId({ provider, name }) + if (type === 'ipfs-ns') { + url = `https://gateway.ipfs.io/ipfs/${hash}${path}${search || ''}` + try { + // check if ipfs gateway has result + const response = await fetch(url, { method: 'HEAD' }) + // if failure, redirect to 404 page + if (response.status !== 200) { + extension.tabs.update(tabId, { url: '404.html' }) + return + } + // otherwise redirect to the correct page + extension.tabs.update(tabId, { url }) + } catch (err) { + console.warn(err) + // if HEAD fetch failed, redirect so user can see relevant error page + extension.tabs.update(tabId, { url }) } - // otherwise redirect to the correct page - extension.tabs.update(tabId, { url }) - } catch (err) { - console.warn(err) - // if HEAD fetch failed, redirect so user can see relevant error page - extension.tabs.update(tabId, { url }) + } else if (type === 'swarm-ns') { + url = `https://swarm-gateways.net/bzz:/${hash}${path}${search || ''}` } + extension.tabs.update(tabId, { url }) } catch (err) { console.warn(err) extension.tabs.update(tabId, { url: `error.html?name=${name}` }) -- cgit