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 {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) {
let result;
let searchValue = payload.searchValue;
let isENSName = false;
if (searchValue.endsWith('.eth')) {
isENSName = true;
const foundEnsExt = ENS_WHITELIST.find(ensExt => searchValue.endsWith(ensExt));
if (foundEnsExt) {
yield fetchEnsRecord({name: payload.searchValue});
const ensRecord = yield select(getEnsRecordForName, searchValue);
@ -63,7 +67,7 @@ export function *searchExplorer(entity, payload) {
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`}));
}

View File

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

View File

@ -249,7 +249,7 @@ class BlockchainConnector {
function checkVersion(next) {
// TODO: web3_clientVersion method is currently not implemented in web3.js 1.0
self.web3._requestManager.send({method: 'web3_clientVersion', params: []}, (err, version) => {
if (err) {
if (err || !version) {
self.isWeb3Ready = false;
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] === "$") {
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 parseArg(arg, nextEachCb);
}
return nextSubEachCb(err, name);
});
} else {
nextSubEachCb(null, sub_arg);
if (Array.isArray(arg)) {
return checkArgs(arg, nextEachCb);
}
}, (err, subRealArgs) => {
nextEachCb(null, subRealArgs);
});
} else if(typeof arg === 'string' && arg.indexOf('.eth') === arg.length - 4) {
self.events.request("ens:resolve", arg, (err, name) => {
if(err) {
self.events.request('ens:isENSName', arg, (isENSName) => {
if (isENSName) {
return self.events.request("ens:resolve", arg, (err, address) => {
if (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) {

View File

@ -43,8 +43,8 @@ function registerSubDomain(ens, registrar, resolver, defaultAccount, subdomain,
callback(null, transaction);
})
.catch(err => {
logger.error(err.message || err);
callback('Failed to register with error: ' + (err.message || err));
logger.error('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 ENSFunctions = require('./ENSFunctions');
import { ZERO_ADDRESS } from '../../utils/addressUtils';
import {ens} from '../../constants';
const ENS_WHITELIST = ens.whitelist;
const MAINNET_ID = '1';
const ROPSTEN_ID = '3';
@ -65,6 +68,7 @@ class ENS {
this.configured = false;
this.events.setCommandHandler("ens:resolve", this.ensResolve.bind(this));
this.events.setCommandHandler("ens:isENSName", this.isENSName.bind(this));
if (this.namesConfig === {} ||
this.namesConfig.enabled !== true ||
@ -148,8 +152,8 @@ class ENS {
// Code inspired by https://github.com/monkybrain/ipfs-to-ens
const {name, storageHash} = options;
if (!utils.isValidEthDomain(name)) {
return cb('Invalid domain name ' + name);
if (!this.isENSName(name)) {
return cb(__('Invalid domain name: {{name}}\nValid extensions are: {{extenstions}}', {name, extenstions: ENS_WHITELIST.join(', ')}));
}
let hashedName = namehash.hash(name);
@ -157,7 +161,7 @@ class ENS {
try {
contentHash = utils.hashTo32ByteHexString(storageHash);
} catch (e) {
return cb('Invalid IPFS hash');
return cb(__('Invalid IPFS hash'));
}
// Set content
async.waterfall([
@ -339,10 +343,18 @@ class ENS {
return next(err);
});
},
function registrar(next) {
function checkRootNode(next) {
if (!self.registration || !self.registration.rootDomain) {
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 rootNode = namehash.hash(self.registration.rootDomain);
const contract = self.ensConfig.FIFSRegistrar;
@ -480,6 +492,16 @@ class ENS {
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;

View File

@ -18,9 +18,9 @@ class TransactionTracker {
}
onBlockHeader(blockHeader) {
this.events.request("blockchain:block:byNumber", blockHeader.hash, (err, block) => {
this.events.request("blockchain:block:byNumber", blockHeader.number , (err, block) => {
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
if (!block || !block.transactions) {

View File

@ -338,13 +338,6 @@ function 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) {
var Web3EthAbi = require('web3-eth-abi');
return Web3EthAbi.decodeParameters(typesArray, hexString);
@ -588,7 +581,6 @@ module.exports = {
isHex,
hashTo32ByteHexString,
isValidDomain,
isValidEthDomain,
pingEndpoint,
decodeParams,
runCmd,

View File

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

View File

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