blob: 9ac852c7605dff9d7dfacad551bd83ae1c6bec4a [file] [log] [blame]
#!/usr/bin/env nodejs
/*
* Copyright (c) 2016-2020 Savoir-faire Linux Inc.
*
* Author: Adrien BĂ©raud <adrien.beraud@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
'use strict';
var async = require("async");
var BigNumber = require('bignumber.js');
var fs = require('fs');
var Web3 = require('web3');
var web3 = new Web3();
var path = require('path');
var fs = require('fs');
var argv = require('minimist')(process.argv.slice(2));
if(argv['_'] < 1)
throw ("Specify Batch Input File as: nodejs " + path.basename(__filename) + " <filename>" );
function validateFile(filename){
if ( path.isAbsolute(filename) && fs.existsSync(filename) )
return filename
else if ( !path.isAbsolute(filename) && fs.existsSync("./" +filename))
return path.resolve(filename)
return false
}
var providedPath = String(argv['_'][0])
batchInputFile = validateFile(providedPath);
if(!batchInputFile)
throw "File " + providedPath + " does not exist"
Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, mined_cb) {
var ethP = this;
var tries = 5;
var filter = this.filter('latest');
filter.watch(function(error, result) {
if (error)
console.log("watch error: " + error);
var receipt = ethP.getTransactionReceipt(txhash);
if (receipt && receipt.transactionHash == txhash) {
filter.stopWatching();
mined_cb();
} else if (!--tries) {
mined_cb("Transaction timeout..");
}
});
}
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
var coinbase = web3.eth.coinbase;
console.log("Coinbase: "+ coinbase);
var balance = web3.eth.getBalance(coinbase);
console.log("Balance:" +balance.toString(10));
var REG_FILE = __dirname + "/contract/registrar.out.json";
var REG_ADDR_FILE = __dirname + "/contractAddress.txt";
var NAME_VALIDATOR = new RegExp('^[a-z0-9-_]{3,32}$');
var account;
var regAddress = "0xe53cb2ace8707526a5050bec7bcf979c57f8b44f";
var regData;
var regContract;
var reg;
function unlockAccount() {
web3.personal.unlockAccount(coinbase, "toto");
}
function getRemainingGaz() {
return web3.eth.getBalance(coinbase) / web3.eth.gasPrice;
}
function loadContract(onContractLoaded) {
fs.readFile(REG_ADDR_FILE, function(err, content) {
if (err) {
throw "Contract Address issues, run server to initialize contract address first time";
} else {
regAddress = String(content).trim();
}
fs.readFile(REG_FILE, function(err, data){
if (err) {
console.log("Can't read contract ABI: " + err);
throw err;
}
regData = JSON.parse(data).contracts.registrar.GlobalRegistrar;
regContract = web3.eth.contract(regData.abi);
console.log("Loading name contract from blockchain at " + regAddress);
web3.eth.getCode(regAddress, function(error, result) {
if (error)
console.log("Error getting contract code: " + error);
if (!result || result == "0x") {
console.log("Contract not found at " + regAddress);
throw "Contract Address issues, run server to initialize contract address"
} else {
regContract.at(regAddress, function(err, result) {
console.log("Contract found and loaded from " + regAddress);
if(!err) {
reg = result;
onContractLoaded();
}
else {
console.error("err: " + err);
}
});
}
});
});
});
}
function checkName(name) {
try {
return Boolean(name.match(NAME_VALIDATOR));
} catch (e) {
return false;
}
}
function formatName(name) {
return '0x' + new Buffer(name, 'utf8').toString('hex');
}
function isHashZero(h) {
return !h || h == "0x" || h == "0x0" || h == "0x0000000000000000000000000000000000000000";
}
function parseString(s) {
return s ? web3.toUtf8(s) : s;
}
function formatAddress(address) {
if (address) {
var s = address.trim();
try {
if (s.startsWith("ring:"))
s = s.substr(5);
if (!s.startsWith("0x"))
s = "0x" + s;
if (new BigNumber(s.substr(2), 16) == 0)
return undefined;
return s;
} catch (err) {}
}
return undefined;
}
function registerName(addressparam, nameparam, ownerparam, pk, sig, mined_cb){
try {
var addr = formatAddress(addressparam);
if (!addr) {
console.log("Error parsing input address "+ addressparam);
return;
}
try {
ownerparam = formatAddress(ownerparam);
if (!ownerparam)
throw "no owner";
} catch (err) {
console.log("Error parsing input: " + err);
return;
}
if (!checkName(nameparam)) {
console.log("error: invalid name "+ nameparam);
return;
}
console.log("Got reg request (" + nameparam + " -> " + addr + ") from " + ownerparam);
reg.owner(nameparam, function(err, owner) {
if (owner == 0) {
reg.name(addr, function(err, res) {
try {
if (err)
console.log("Error checking name: " + err);
var name = parseString(res);
if (name) {
console.log("Address " + addr + " already registered with name: " + name);
return;
} else {
console.log("Remaing gaz: " + getRemainingGaz());
unlockAccount();
reg.reserveFor.sendTransaction(formatName(nameparam), ownerparam, addr, pk, sig, {
from: coinbase,
gas: 3000000
}, function(terr, reg_c) {
if (terr) {
console.log("Transaction error " + JSON.stringify(terr));
} else {
console.log("Transaction sent " + reg_c);
// Send answer as soon as the transaction is queued
console.log("Success!")
web3.eth.awaitConsensus(reg_c, function(error) {
mined_cb(reg_c)
if (error) {
console.log(error);
return;
}
});
}
});
}
} catch (err) {
console.log("Address registration exception: " + err);
}
});
} else {
if (owner == ownerparam) {
reg.addr(nameparam, function(err, reg_addr) {
if (reg_addr == addr) {
console.log("Success!");
return;
} else {
console.log("Error!" + err);
return;
}
});
} else {
console.log("Error!");;
console.log("Owner "+ owner);
console.log("Ownerparam "+ ownerparam);
return;
}
}
});
} catch (err) {
console.log("Address registration exception: " + err);
}
}
function startWrites(){
var NAME_LIST = JSON.parse(fs.readFileSync(batchInputFile, 'utf8'));
console.log(String(NAME_LIST.length) + " inserts to do");
//create parallel queue that does 256 registerNames parallely
var q = async.queue(function(task, callback) {
registerName(task['addr'], task['name'], task['owner'], task['publickey'], task['signature'], callback);
}, 256);
for (var i = 0; i < NAME_LIST.length; i++) {
q.push(NAME_LIST[i], function(c){console.log("Mined registry: "+ c)});
console.log("Queued " + i);
}
}
unlockAccount();
loadContract(startWrites);