refactor(ENS): adds a whitelist for ens

Enables only the use of domains in that white list
This commit is contained in:
Jonathan Rainville 2018-11-22 08:47:39 -05:00 committed by Iuri Matias
parent bae31165dd
commit d09d410021
10 changed files with 78 additions and 52 deletions

View File

@ -3,12 +3,16 @@ import {getAccounts, getBlocks, getTransactions, getContracts, getEnsRecordForNa
import {fetchAccounts, fetchBlocks, fetchTransactions, fetchContracts, fetchEnsRecord} from "./index"; import {fetchAccounts, fetchBlocks, fetchTransactions, fetchContracts, fetchEnsRecord} from "./index";
import {ELEMENTS_LIMIT} from '../constants'; import {ELEMENTS_LIMIT} from '../constants';
const ENS_WHITELIST = [
".eth",
".xyz"
]; // Putting this here as I can't import from embark's constants
export function *searchExplorer(entity, payload) { export function *searchExplorer(entity, payload) {
let result; let result;
let searchValue = payload.searchValue; let searchValue = payload.searchValue;
let isENSName = false; const foundEnsExt = ENS_WHITELIST.find(ensExt => searchValue.endsWith(ensExt));
if (searchValue.endsWith('.eth')) { if (foundEnsExt) {
isENSName = true;
yield fetchEnsRecord({name: payload.searchValue}); yield fetchEnsRecord({name: payload.searchValue});
const ensRecord = yield select(getEnsRecordForName, searchValue); const ensRecord = yield select(getEnsRecordForName, searchValue);
@ -63,7 +67,7 @@ export function *searchExplorer(entity, payload) {
return yield put(entity.success(result)); return yield put(entity.success(result));
} }
if (isENSName) { if (foundEnsExt) {
return yield put(entity.success({error: `ENS resolved to ${searchValue}, but Embark couldn't find what this address represents`})); return yield put(entity.success({error: `ENS resolved to ${searchValue}, but Embark couldn't find what this address represents`}));
} }

View File

@ -63,5 +63,11 @@
"implicit": "implicit", "implicit": "implicit",
"explicit": "explicit" "explicit": "explicit"
}, },
"embarkResourceOrigin": "http://embark" "embarkResourceOrigin": "http://embark",
"ens": {
"whitelist": [
"eth",
"xyz"
]
}
} }

View File

@ -249,7 +249,7 @@ class BlockchainConnector {
function checkVersion(next) { function checkVersion(next) {
// TODO: web3_clientVersion method is currently not implemented in web3.js 1.0 // TODO: web3_clientVersion method is currently not implemented in web3.js 1.0
self.web3._requestManager.send({method: 'web3_clientVersion', params: []}, (err, version) => { self.web3._requestManager.send({method: 'web3_clientVersion', params: []}, (err, version) => {
if (err) { if (err || !version) {
self.isWeb3Ready = false; self.isWeb3Ready = false;
return next(null, {name: "Ethereum node not found", status: 'off'}); return next(null, {name: "Ethereum node not found", status: 'off'});
} }

View File

@ -50,37 +50,32 @@ class ContractDeployer {
}); });
} }
async.map(args, (arg, nextEachCb) => { function checkArgs(argus, cb) {
async.map(argus, (arg, nextEachCb) => {
if (arg[0] === "$") { if (arg[0] === "$") {
parseArg(arg, nextEachCb); return parseArg(arg, nextEachCb);
} else if (Array.isArray(arg)) {
async.map(arg, (sub_arg, nextSubEachCb) => {
if (sub_arg[0] === "$") {
parseArg(sub_arg, nextSubEachCb);
} else if(typeof sub_arg === 'string' && sub_arg.indexOf('.eth') === sub_arg.length - 4) {
self.events.request("ens:resolve", sub_arg, (err, name) => {
if(err) {
return nextSubEachCb(err);
} }
return nextSubEachCb(err, name);
}); if (Array.isArray(arg)) {
} else { return checkArgs(arg, nextEachCb);
nextSubEachCb(null, sub_arg);
} }
}, (err, subRealArgs) => {
nextEachCb(null, subRealArgs); self.events.request('ens:isENSName', arg, (isENSName) => {
}); if (isENSName) {
} else if(typeof arg === 'string' && arg.indexOf('.eth') === arg.length - 4) { return self.events.request("ens:resolve", arg, (err, address) => {
self.events.request("ens:resolve", arg, (err, name) => {
if (err) { if (err) {
return nextEachCb(err); return nextEachCb(err);
} }
return nextEachCb(err, name); nextEachCb(err, address);
}); });
} else {
nextEachCb(null, arg);
} }
}, callback);
nextEachCb(null, arg);
});
}, cb);
}
checkArgs(args, callback);
} }
checkAndDeployContract(contract, params, callback) { checkAndDeployContract(contract, params, callback) {

View File

@ -43,8 +43,8 @@ function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain,
callback(null, transaction); callback(null, transaction);
}) })
.catch(err => { .catch(err => {
logger.error(err.message || err); logger.error('Failed to register with error:', err.message || err);
callback('Failed to register with error: ' + (err.message || err)); callback(err.message || err);
}); });
} }

View File

@ -6,6 +6,9 @@ const embarkJsUtils = require('embarkjs').Utils;
const reverseAddrSuffix = '.addr.reverse'; const reverseAddrSuffix = '.addr.reverse';
const ENSFunctions = require('./ENSFunctions'); const ENSFunctions = require('./ENSFunctions');
import { ZERO_ADDRESS } from '../../utils/addressUtils'; import { ZERO_ADDRESS } from '../../utils/addressUtils';
import {ens} from '../../constants';
const ENS_WHITELIST = ens.whitelist;
const MAINNET_ID = '1'; const MAINNET_ID = '1';
const ROPSTEN_ID = '3'; const ROPSTEN_ID = '3';
@ -65,6 +68,7 @@ class ENS {
this.configured = false; this.configured = false;
this.events.setCommandHandler("ens:resolve", this.ensResolve.bind(this)); this.events.setCommandHandler("ens:resolve", this.ensResolve.bind(this));
this.events.setCommandHandler("ens:isENSName", this.isENSName.bind(this));
if (this.namesConfig === {} || if (this.namesConfig === {} ||
this.namesConfig.enabled !== true || this.namesConfig.enabled !== true ||
@ -148,8 +152,8 @@ class ENS {
// Code inspired by https://github.com/monkybrain/ipfs-to-ens // Code inspired by https://github.com/monkybrain/ipfs-to-ens
const {name, storageHash} = options; const {name, storageHash} = options;
if (!utils.isValidEthDomain(name)) { if (!this.isENSName(name)) {
return cb('Invalid domain name ' + name); return cb(__('Invalid domain name: {{name}}\nValid extensions are: {{extenstions}}', {name, extenstions: ENS_WHITELIST.join(', ')}));
} }
let hashedName = namehash.hash(name); let hashedName = namehash.hash(name);
@ -157,7 +161,7 @@ class ENS {
try { try {
contentHash = utils.hashTo32ByteHexString(storageHash); contentHash = utils.hashTo32ByteHexString(storageHash);
} catch (e) { } catch (e) {
return cb('Invalid IPFS hash'); return cb(__('Invalid IPFS hash'));
} }
// Set content // Set content
async.waterfall([ async.waterfall([
@ -339,10 +343,18 @@ class ENS {
return next(err); return next(err);
}); });
}, },
function registrar(next) { function checkRootNode(next) {
if (!self.registration || !self.registration.rootDomain) { if (!self.registration || !self.registration.rootDomain) {
return next(NO_REGISTRATION); return next(NO_REGISTRATION);
} }
if (!self.isENSName(self.registration.rootDomain)) {
return next(__('Invalid domain name: {{name}}\nValid extensions are: {{extenstions}}',
{name: self.registration.rootDomain, extenstions: ENS_WHITELIST.join(', ')}));
}
next();
},
function registrar(next) {
const registryAddress = self.ensConfig.ENSRegistry.deployedAddress; const registryAddress = self.ensConfig.ENSRegistry.deployedAddress;
const rootNode = namehash.hash(self.registration.rootDomain); const rootNode = namehash.hash(self.registration.rootDomain);
const contract = self.ensConfig.FIFSRegistrar; const contract = self.ensConfig.FIFSRegistrar;
@ -480,6 +492,16 @@ class ENS {
cb(null, result); cb(null, result);
}); });
} }
isENSName(name, callback = () => {}) {
if (typeof name !== 'string') {
callback(false);
return false;
}
const result = Boolean(ENS_WHITELIST.find(ensExt => name.endsWith(ensExt)));
callback(result);
return result;
}
} }
module.exports = ENS; module.exports = ENS;

View File

@ -18,9 +18,9 @@ class TransactionTracker {
} }
onBlockHeader(blockHeader) { onBlockHeader(blockHeader) {
this.events.request("blockchain:block:byNumber", blockHeader.hash, (err, block) => { this.events.request("blockchain:block:byNumber", blockHeader.number , (err, block) => {
if (err) { if (err) {
return this.logger.error('Error getting block header', err); return this.logger.error('Error getting block header', err.message || err);
} }
// Don't know why, but sometimes we receive nothing // Don't know why, but sometimes we receive nothing
if (!block || !block.transactions) { if (!block || !block.transactions) {

View File

@ -338,13 +338,6 @@ function isValidDomain(domain) {
return isValidDomain(domain); return isValidDomain(domain);
} }
function isValidEthDomain(ethDomain) {
if (!isValidDomain(ethDomain)) {
return false;
}
return ethDomain.substring(ethDomain.lastIndexOf('.'), ethDomain.length) === '.eth';
}
function decodeParams(typesArray, hexString) { function decodeParams(typesArray, hexString) {
var Web3EthAbi = require('web3-eth-abi'); var Web3EthAbi = require('web3-eth-abi');
return Web3EthAbi.decodeParameters(typesArray, hexString); return Web3EthAbi.decodeParameters(typesArray, hexString);
@ -588,7 +581,6 @@ module.exports = {
isHex, isHex,
hashTo32ByteHexString, hashTo32ByteHexString,
isValidDomain, isValidDomain,
isValidEthDomain,
pingEndpoint, pingEndpoint,
decodeParams, decodeParams,
runCmd, runCmd,

View File

@ -1,8 +1,7 @@
pragma solidity ^0.4.24; pragma solidity ^0.4.24;
contract AnotherStorage { contract AnotherStorage {
address public simpleStorageAddress; address public simpleStorageAddress;
address simpleStorageAddress2; address public ens;
address ens;
constructor(address addr, address _ens) public { constructor(address addr, address _ens) public {
simpleStorageAddress = addr; simpleStorageAddress = addr;

View File

@ -2,6 +2,7 @@
const assert = require('assert'); const assert = require('assert');
const AnotherStorage = require('Embark/contracts/AnotherStorage'); const AnotherStorage = require('Embark/contracts/AnotherStorage');
const SimpleStorage = require('Embark/contracts/SimpleStorage'); const SimpleStorage = require('Embark/contracts/SimpleStorage');
let accounts;
config({ config({
contracts: { contracts: {
@ -12,13 +13,20 @@ config({
args: ["$SimpleStorage", "embark.eth"] args: ["$SimpleStorage", "embark.eth"]
} }
} }
}, (err, accs) => {
accounts = accs;
}); });
contract("AnotherStorage", function() { contract("AnotherStorage", function() {
this.timeout(0); this.timeout(0);
it("set SimpleStorage address", async function() { it("set SimpleStorage address", async function() {
let result = await AnotherStorage.methods.simpleStorageAddress().call(); const result = await AnotherStorage.methods.simpleStorageAddress().call();
assert.equal(result.toString(), SimpleStorage.options.address); assert.equal(result.toString(), SimpleStorage.options.address);
}); });
it("set ENS address", async function() {
const result = await AnotherStorage.methods.ens().call();
assert.equal(result.toString(), accounts[0]);
});
}); });