Skip to content
Snippets Groups Projects
Commit 24aa2a0c authored by Félix  Sidokhine's avatar Félix Sidokhine
Browse files

nameservice: public-key and signature now stored on blockchain

The public-key and signature can now be POSTed at time of registration
These are validated by server before posting to blockchain, and can be
retrieved by users for validation on their local machines as well

Added appropriate HTTP codes as well

Modified contract to store and retrieve these values and various scripts
(server, batch reading/writing) to handle these new values

Change-Id: Iddcaa00ab0d7068cea6d578489eacb89e8354b7c
parent 232fe05c
Branches
No related tags found
No related merge requests found
pragma solidity ^0.4.0; pragma solidity ^0.5.2;
/* /*
* Copyright (c) 2014 Gav Wood <g@ethdev.com> * Copyright (c) 2014 Gav Wood <g@ethdev.com>
* Copyright (c) 2016 Savoir-faire Linux Inc. * Copyright (c) 2016 Savoir-faire Linux Inc.
...@@ -26,24 +26,26 @@ pragma solidity ^0.4.0; ...@@ -26,24 +26,26 @@ pragma solidity ^0.4.0;
*/ */
contract NameRegister { contract NameRegister {
function addr(bytes32 _name) constant returns (address o_owner) {} function addr(bytes32 _name) public view returns (address o_owner) {}
function name(address _owner) constant returns (bytes32 o_name) {} function name(address _owner) public view returns (bytes32 o_name) {}
} }
contract Registrar is NameRegister { contract Registrar is NameRegister {
event Changed(bytes32 indexed name); event Changed(bytes32 indexed name);
event PrimaryChanged(bytes32 indexed name, address indexed addr, address owner); event PrimaryChanged(bytes32 indexed name, address indexed addr, address owner);
function owner(bytes32 _name) constant returns (address o_owner) {} function owner(bytes32 _name) public view returns (address o_owner) {}
function addr(bytes32 _name) constant returns (address o_address) {} function addr(bytes32 _name) public view returns (address o_address) {}
function subRegistrar(bytes32 _name) constant returns (address o_subRegistrar) {} function subRegistrar(bytes32 _name) public view returns (address o_subRegistrar) {}
function content(bytes32 _name) constant returns (bytes32 o_content) {} function content(bytes32 _name) public view returns (bytes32 o_content) {}
function name(address _owner) constant returns (bytes32 o_name) {} function name(address _owner) public view returns (bytes32 o_name) {}
} }
contract GlobalRegistrar is Registrar { contract GlobalRegistrar is Registrar {
struct Record { struct Record {
string publicKey;
string signedName;
address owner; address owner;
address primary; address primary;
address subRegistrar; address subRegistrar;
...@@ -52,68 +54,70 @@ contract GlobalRegistrar is Registrar { ...@@ -52,68 +54,70 @@ contract GlobalRegistrar is Registrar {
uint renewalDate; uint renewalDate;
} }
function Registrar() { function reserve(bytes32 _name, address _a) public {
} if (m_toRecord[_name].owner == address(0) && m_toName[_a] == 0) {
function reserve(bytes32 _name, address _a) {
if (m_toRecord[_name].owner == 0 && m_toName[_a] == 0) {
m_toRecord[_name].owner = msg.sender; m_toRecord[_name].owner = msg.sender;
m_toRecord[_name].primary = _a; m_toRecord[_name].primary = _a;
m_toName[_a] = _name; m_toName[_a] = _name;
Changed(_name); emit Changed(_name);
PrimaryChanged(_name, _a, msg.sender); emit PrimaryChanged(_name, _a, msg.sender);
} }
} }
function reserveFor(bytes32 _name, address _owner, address _a) { function reserveFor(bytes32 _name, address _owner, address _a, string memory _publickey, string memory _signedname) public {
if (m_toRecord[_name].owner == 0 && m_toName[_a] == 0) { if (m_toRecord[_name].owner == address(0) && m_toName[_a] == 0) {
m_toRecord[_name].owner = _owner; m_toRecord[_name].owner = _owner;
m_toRecord[_name].primary = _a; m_toRecord[_name].primary = _a;
m_toRecord[_name].publicKey = _publickey;
m_toRecord[_name].signedName = _signedname;
m_toName[_a] = _name; m_toName[_a] = _name;
Changed(_name); emit Changed(_name);
PrimaryChanged(_name, _a, _owner); emit PrimaryChanged(_name, _a, _owner);
} }
} }
modifier onlyrecordowner(bytes32 _name) { if (m_toRecord[_name].owner == msg.sender) _; } modifier onlyrecordowner(bytes32 _name) { if (m_toRecord[_name].owner == msg.sender) _; }
function transfer(bytes32 _name, address _newOwner) onlyrecordowner(_name) { function transfer(bytes32 _name, address _newOwner) public onlyrecordowner(_name) {
m_toRecord[_name].owner = _newOwner; m_toRecord[_name].owner = _newOwner;
Changed(_name); emit Changed(_name);
} }
function disown(bytes32 _name) onlyrecordowner(_name) { function disown(bytes32 _name) public onlyrecordowner(_name) {
if (m_toName[m_toRecord[_name].primary] == _name) if (m_toName[m_toRecord[_name].primary] == _name)
{ {
PrimaryChanged(_name, m_toRecord[_name].primary, m_toRecord[_name].owner); emit PrimaryChanged(_name, m_toRecord[_name].primary, m_toRecord[_name].owner);
m_toName[m_toRecord[_name].primary] = ""; m_toName[m_toRecord[_name].primary] = "";
} }
delete m_toRecord[_name]; delete m_toRecord[_name];
Changed(_name); emit Changed(_name);
} }
function setAddress(bytes32 _name, address _a, bool _primary) onlyrecordowner(_name) { function setAddress(bytes32 _name, address _a, bool _primary) public onlyrecordowner(_name) {
m_toRecord[_name].primary = _a; m_toRecord[_name].primary = _a;
if (_primary) if (_primary)
{ {
PrimaryChanged(_name, _a, m_toRecord[_name].owner); emit PrimaryChanged(_name, _a, m_toRecord[_name].owner);
m_toName[_a] = _name; m_toName[_a] = _name;
} }
Changed(_name); emit Changed(_name);
} }
function setSubRegistrar(bytes32 _name, address _registrar) onlyrecordowner(_name) { function setSubRegistrar(bytes32 _name, address _registrar) public onlyrecordowner(_name) {
m_toRecord[_name].subRegistrar = _registrar; m_toRecord[_name].subRegistrar = _registrar;
Changed(_name); emit Changed(_name);
} }
function setContent(bytes32 _name, bytes32 _content) onlyrecordowner(_name) { function setContent(bytes32 _name, bytes32 _content) public onlyrecordowner(_name) {
m_toRecord[_name].content = _content; m_toRecord[_name].content = _content;
Changed(_name); emit Changed(_name);
} }
function owner(bytes32 _name) constant returns (address) { return m_toRecord[_name].owner; } function owner(bytes32 _name) public view returns (address) { return m_toRecord[_name].owner; }
function addr(bytes32 _name) constant returns (address) { return m_toRecord[_name].primary; } function addr(bytes32 _name) public view returns (address) { return m_toRecord[_name].primary; }
function register(bytes32 _name) constant returns (address) { return m_toRecord[_name].subRegistrar; } function register(bytes32 _name) public view returns (address) { return m_toRecord[_name].subRegistrar; }
function content(bytes32 _name) constant returns (bytes32) { return m_toRecord[_name].content; } function content(bytes32 _name) public view returns (bytes32) { return m_toRecord[_name].content; }
function name(address _a) constant returns (bytes32 o_name) { return m_toName[_a]; } function name(address _a) public view returns (bytes32 o_name) { return m_toName[_a]; }
function publickey(bytes32 _name) public view returns (string memory) { return m_toRecord[_name].publicKey; }
function signature(bytes32 _name) public view returns (string memory) { return m_toRecord[_name].signedName; }
mapping (address => bytes32) m_toName; mapping (address => bytes32) m_toName;
mapping (bytes32 => Record) m_toRecord; mapping (bytes32 => Record) m_toRecord;
......
...@@ -18,15 +18,38 @@ ...@@ -18,15 +18,38 @@
*/ */
'use strict'; 'use strict';
var express = require('express'); const express = require('express');
var bodyParser = require('body-parser'); const bodyParser = require('body-parser');
var BigNumber = require('bignumber.js'); const BigNumber = require('bignumber.js');
var fs = require('fs'); const fs = require('fs');
var http = require('http'); const http = require('http');
var https = require('https'); const https = require('https');
var Web3 = require('web3'); const Web3 = require('web3');
var web3 = new Web3(); const web3 = new Web3();
var argv = require('minimist')(process.argv.slice(2)); const argv = require('minimist')(process.argv.slice(2));
const crypto = require('crypto');
const path = require('path');
//Patch to support caching.
//map of form {name,address}
const cache = {};
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
}
function loadCache(batchInputFile) {
const NAME_LIST = JSON.parse(fs.readFileSync(batchInputFile, 'utf8'));
for (const entry of Object.entries(NAME_LIST)) {
cache[entry[0]] = entry[1]
}
}
Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, mined_cb) { Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, mined_cb) {
var ethP = this; var ethP = this;
...@@ -46,25 +69,45 @@ Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, mined_cb) { ...@@ -46,25 +69,45 @@ Object.getPrototypeOf(web3.eth).awaitConsensus = function(txhash, mined_cb) {
} }
web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545')); web3.setProvider(new web3.providers.HttpProvider('http://localhost:8545'));
var coinbase = web3.eth.coinbase; const coinbase = web3.eth.coinbase;
console.log(coinbase); console.log(coinbase);
var balance = web3.eth.getBalance(coinbase); let balance = web3.eth.getBalance(coinbase);
console.log(balance.toString(10)); console.log(balance.toString(10));
var REG_FILE = __dirname + "/contract/registrar.out.json"; const REG_FILE = __dirname + "/contract/registrar.out.json";
var REG_ADDR_FILE = __dirname + "/contractAddress.txt"; const REG_ADDR_FILE = __dirname + "/contractAddress.txt";
var NAME_VALIDATOR = new RegExp('^[a-z0-9-_]{3,32}$'); const NAME_VALIDATOR = new RegExp('^[a-z0-9-_]{3,32}$');
var account; let account;
var regAddress = "0xe53cb2ace8707526a5050bec7bcf979c57f8b44f"; let regAddress = "0xe53cb2ace8707526a5050bec7bcf979c57f8b44f";
var regData; let regData;
var regContract; let regContract;
var reg; let reg;
const cache = {};
function loadNames(filename){
console.log("The cache will be populated with the data from the export file!");
const providedPath = String(argv['_'][0]);
const batchInputFile = validateFile(providedPath);
if(!batchInputFile){
throw "File " + providedPath + " does not exist";
}
else{
loadCache(batchInputFile);
}
}
function verifySignature(name, _publickey, signature){
const publicKey = new Buffer(_publickey, 'base64').toString('ascii')
const verifier = crypto.createVerify('RSA-SHA512');
verifier.update(name);
const ver = verifier.verify(publicKey, signature,'base64');
return ver;
}
function unlockAccount() { function unlockAccount() {
web3.personal.unlockAccount(coinbase, "toto"); web3.personal.unlockAccount(coinbase, "apple123");
} }
function getRemainingGaz() { function getRemainingGaz() {
...@@ -76,8 +119,8 @@ function waitForGaz(want, cb) { ...@@ -76,8 +119,8 @@ function waitForGaz(want, cb) {
cb(); cb();
return; return;
} }
var timeout = function() { const timeout = () => {
var g = getRemainingGaz(); const g = getRemainingGaz();
if (g >= want) { if (g >= want) {
//web3.miner.stop(); //web3.miner.stop();
console.log("Mining finished ! Now having " + g + " gaz."); console.log("Mining finished ! Now having " + g + " gaz.");
...@@ -91,8 +134,8 @@ function waitForGaz(want, cb) { ...@@ -91,8 +134,8 @@ function waitForGaz(want, cb) {
timeout(); timeout();
} }
function loadContract() { function loadContract(onContractLoaded) {
fs.readFile(REG_ADDR_FILE, function(err, content) { fs.readFile(REG_ADDR_FILE, (err, content) => {
if (err) { if (err) {
console.log("Can't read contract address: " + err); console.log("Can't read contract address: " + err);
} else { } else {
...@@ -111,13 +154,13 @@ function loadContract() { ...@@ -111,13 +154,13 @@ function loadContract() {
console.log("Error getting contract code: " + error); console.log("Error getting contract code: " + error);
if (!result || result == "0x") { if (!result || result == "0x") {
console.log("Contract not found at " + regAddress); console.log("Contract not found at " + regAddress);
initContract(); initContract(onContractLoaded);
} else { } else {
regContract.at(regAddress, function(err, result) { regContract.at(regAddress, function(err, result) {
console.log("Contract found and loaded from " + regAddress); console.log("Contract found and loaded from " + regAddress);
if(!err) { if(!err) {
reg = result; reg = result;
startServer(); onContractLoaded(reg)
} }
else { else {
console.error("err: " + err); console.error("err: " + err);
...@@ -129,7 +172,7 @@ function loadContract() { ...@@ -129,7 +172,7 @@ function loadContract() {
}); });
} }
function initContract() { function initContract(onContractInitialized) {
waitForGaz(3000000, function(){ waitForGaz(3000000, function(){
regContract.new({ from: coinbase, regContract.new({ from: coinbase,
data: '0x'+regData.evm.bytecode.object, data: '0x'+regData.evm.bytecode.object,
...@@ -142,7 +185,7 @@ function initContract() { ...@@ -142,7 +185,7 @@ function initContract() {
regAddress = contract.address; regAddress = contract.address;
fs.writeFileSync(REG_ADDR_FILE, regAddress); fs.writeFileSync(REG_ADDR_FILE, regAddress);
reg = contract; reg = contract;
startServer(); onContractInitialized();
} }
} else { } else {
console.log(e); console.log(e);
...@@ -173,7 +216,7 @@ function parseString(s) { ...@@ -173,7 +216,7 @@ function parseString(s) {
function formatAddress(address) { function formatAddress(address) {
if (address) { if (address) {
var s = address.trim(); let s = address.trim();
try { try {
if (s.startsWith("ring:")) if (s.startsWith("ring:"))
s = s.substr(5); s = s.substr(5);
...@@ -188,8 +231,8 @@ function formatAddress(address) { ...@@ -188,8 +231,8 @@ function formatAddress(address) {
} }
function readCertificateChain(path) { function readCertificateChain(path) {
var cert = []; let cert = [];
var ca = []; const ca = [];
fs.readFileSync(path, 'utf8').split("\n").forEach(function(line) { fs.readFileSync(path, 'utf8').split("\n").forEach(function(line) {
cert.push(line); cert.push(line);
if (line.match(/-END CERTIFICATE-/)) { if (line.match(/-END CERTIFICATE-/)) {
...@@ -200,9 +243,9 @@ function readCertificateChain(path) { ...@@ -200,9 +243,9 @@ function readCertificateChain(path) {
return ca; return ca;
} }
function startServer() { function startServer(result) {
console.log("Starting web server"); console.log("Starting web server");
var app = express(); const app = express();
app.disable('x-powered-by'); app.disable('x-powered-by');
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(function(req, res, next) { app.use(function(req, res, next) {
...@@ -213,19 +256,94 @@ function startServer() { ...@@ -213,19 +256,94 @@ function startServer() {
// Register name lookup handler // Register name lookup handler
app.get("/name/:name", function(req, http_res) { app.get("/name/:name", function(req, http_res) {
try { try {
reg.addr(formatName(req.params.name), function(err, res) { reg.addr(formatName(req.params.name), function(err, res_addr) {
try {
if (err)
console.log("Name lookup error: " + err);
if (isHashZero(res_addr)) {
throw Error("name not registered");
//http_res.status(404).end(JSON.stringify({"error": "name not registered"}));
} else {
reg.publickey(formatName(req.params.name), function(err, res_publickey) {
try {
if (err)
console.log("Name lookup error: " + err);
if (isHashZero(res_publickey)) {
http_res.end(JSON.stringify({"name": req.params.name, "addr": res_addr}));
} else {
reg.signature(formatName(req.params.name), function(err, res_signature) {
try {
if (err)
console.log("Name lookup error: " + err);
if (isHashZero(res_signature)) {
http_res.end(JSON.stringify({"name": req.params.name, "addr": res_addr}));
} else {
http_res.end(JSON.stringify({"name": req.params.name, "addr": res_addr, "publickey": res_publickey, "signature": res_signature }));
}
} catch (err) {
console.log("Name lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"}));
}
});
}
} catch (err) {
console.log("Name lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"}));
}
});
}
} catch (err) {
if(cache[req.params.name] != undefined){
if(cache[req.params.name]['publickey'] && cache[req.params.name]['signature']){
http_res.end(JSON.stringify({"name": req.params.name, "addr": cache[req.params.name]['addr'], "publickey": cache[req.params.name]['publickey'], "signature": cache[req.params.name]['signature']}));
}
else{
http_res.end(JSON.stringify({"name": req.params.name, "addr": cache[req.params.name]['addr']}));
}
}
else{
http_res.status(404).end(JSON.stringify({"error": "name not registered"}));
}
}
});
} catch (err) {
console.log("Name lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"}));
}
});
app.get("/name/:name/publickey", function(req, http_res) {
try {
reg.publickey(formatName(req.params.name), function(err, res) {
try { try {
if (err) if (err)
console.log("Name lookup error: " + err); console.log("Name lookup error: " + err);
if (isHashZero(res)) { if (isHashZero(res)) {
const cachedAddress = cache[req.params.name]; http_res.status(404).end(JSON.stringify({"error": "name not registered"}));
if (cachedAddress != undefined) {
http_res.end(JSON.stringify({"name": req.params.name,"addr": cachedAddress}));
} else { } else {
http_res.status(404).end(JSON.stringify({"error": "name not registred"})); http_res.end(JSON.stringify({"name": req.params.name, "publickey": res }));
}
} catch (err) {
console.log("Name lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"}));
}
});
} catch (err) {
console.log("Name lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"}));
} }
});
app.get("/name/:name/signature", function(req, http_res) {
try {
reg.signature(formatName(req.params.name), function(err, res) {
try {
if (err)
console.log("Name lookup error: " + err);
if (isHashZero(res)) {
http_res.status(404).end(JSON.stringify({"error": "name not registered"}));
} else { } else {
http_res.end(JSON.stringify({"name": req.params.name,"addr": res})); http_res.end(JSON.stringify({"name": req.params.name, "signature": res }));
} }
} catch (err) { } catch (err) {
console.log("Name lookup exception: " + err); console.log("Name lookup exception: " + err);
...@@ -246,7 +364,7 @@ function startServer() { ...@@ -246,7 +364,7 @@ function startServer() {
if (err) if (err)
console.log("Owner lookup error: " + err); console.log("Owner lookup error: " + err);
if (isHashZero(res)) { if (isHashZero(res)) {
http_res.status(404).end(JSON.stringify({"error": "name not registred"})); http_res.status(404).end(JSON.stringify({"error": "name not registered"}));
} else { } else {
http_res.end(JSON.stringify({"name": req.params.name, "owner": res})); http_res.end(JSON.stringify({"name": req.params.name, "owner": res}));
} }
...@@ -254,7 +372,6 @@ function startServer() { ...@@ -254,7 +372,6 @@ function startServer() {
console.log("Owner lookup exception: " + err); console.log("Owner lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"})); http_res.status(500).end(JSON.stringify({"error": "server error"}));
} }
//http_res.end(JSON.stringify({"name": req.params.name,"owner": res}));
}); });
} catch (err) { } catch (err) {
console.log("Owner lookup exception: " + err); console.log("Owner lookup exception: " + err);
...@@ -279,7 +396,7 @@ function startServer() { ...@@ -279,7 +396,7 @@ function startServer() {
if (name) if (name)
http_res.end(JSON.stringify({"name": name})); http_res.end(JSON.stringify({"name": name}));
else else
http_res.status(404).end(JSON.stringify({"error": "address not registred"})); http_res.status(404).end(JSON.stringify({"error": "address not registered"}));
} catch (err) { } catch (err) {
console.log("Address lookup exception: " + err); console.log("Address lookup exception: " + err);
http_res.status(500).end(JSON.stringify({"error": "server error"})); http_res.status(500).end(JSON.stringify({"error": "server error"}));
...@@ -313,8 +430,36 @@ function startServer() { ...@@ -313,8 +430,36 @@ function startServer() {
http_res.status(400).end(JSON.stringify({"success": false, "error": "invalid name"})); http_res.status(400).end(JSON.stringify({"success": false, "error": "invalid name"}));
return; return;
} }
if(cache[req.params.name] == undefined){
http_res.status(400).end(JSON.stringify({"success":false,"error": "name already registered"}));
return;
}
//Temporarily commented out for testing purposes.
//Backward compatibility patch to allow registrations without public keys:
let publickey;
let signature;
if(!req.body.publickey && !req.body.signature){
publickey = 0;
signature = 0;
}
else{
if (!req.body.publickey || req.body.publickey == "") {
http_res.status(400).end(JSON.stringify({"success": false, "error": "publickey not found or invalid"}));
return;
}
if (!req.body.signature || req.body.signature == "") {
http_res.status(400).end(JSON.stringify({"success": false, "error": "signature not found or invalid"}));
}
if(!verifySignature(req.params.name, req.body.publickey, req.body.signature)){
http_res.status(401).end(JSON.stringify({"success": false, "error": "signature verification failed"}));
return;
}
else{
publickey = req.body.publickey;
signature = req.body.signature;
}
}
console.log("Got reg request (" + req.params.name + " -> " + addr + ") from " + req.body.owner); console.log("Got reg request (" + req.params.name + " -> " + addr + ") from " + req.body.owner);
reg.owner(req.params.name, function(err, owner) { reg.owner(req.params.name, function(err, owner) {
if (owner == 0) { if (owner == 0) {
reg.name(addr, function(err, res) { reg.name(addr, function(err, res) {
...@@ -328,7 +473,7 @@ function startServer() { ...@@ -328,7 +473,7 @@ function startServer() {
} else { } else {
console.log("Remaing gaz: " + getRemainingGaz()); console.log("Remaing gaz: " + getRemainingGaz());
unlockAccount(); unlockAccount();
reg.reserveFor.sendTransaction(formatName(req.params.name), req.body.owner, addr, { reg.reserveFor.sendTransaction(formatName(req.params.name), req.body.owner, addr, publickey, signature, {
from: coinbase, from: coinbase,
gas: 3000000 gas: 3000000
}, function(terr, reg_c) { }, function(terr, reg_c) {
...@@ -336,16 +481,21 @@ function startServer() { ...@@ -336,16 +481,21 @@ function startServer() {
console.log("Transaction error " + JSON.stringify(terr)); console.log("Transaction error " + JSON.stringify(terr));
http_res.end(JSON.stringify(terr)); http_res.end(JSON.stringify(terr));
} else { } else {
//Add the registration into the cache.
cache[req.params.name] = {
addr,
publickey,
signature
};
//Now we continue with the sending of the transactions.
console.log("Transaction sent " + reg_c); console.log("Transaction sent " + reg_c);
// Send answer as soon as the transaction is queued // Send answer as soon as the transaction is queued
cache[req.params.name] = addr;
http_res.end(JSON.stringify({"success": true})); http_res.end(JSON.stringify({"success": true}));
web3.eth.awaitConsensus(reg_c, function(error) { web3.eth.awaitConsensus(reg_c, function(error) {
if (error) { if (error) {
console.log(error); console.log(error);
return; return;
} }
delete cache[req.params.name];
console.log("Ended registration for " + req.params.name + " -> " + addr); console.log("Ended registration for " + req.params.name + " -> " + addr);
}); });
} }
...@@ -394,5 +544,8 @@ function startServer() { ...@@ -394,5 +544,8 @@ function startServer() {
} }
} }
if(argv['_'] != 0){
loadNames(argv['_']);
}
unlockAccount(); unlockAccount();
loadContract(); loadContract(startServer);
#!/usr/bin/python3
import os, sys
import time
import argparse
import subprocess as proc
import libtmux
import re
parser = argparse.ArgumentParser(description='Launch Ethereum test nodes in screen')
parser.add_argument('--geth', '-e', default='geth', help='geth executable')
parser.add_argument('--start-port', '-p', type=int, default=4230, help='inital port')
parser.add_argument('--nodes', '-n', type=int, default=8, help='number of nodes')
parser.add_argument('--netid', '-id', type=int, default=4226, help='Ethereum network ID')
parser.add_argument('--datadir', '-d', help='Data directory')
parser.add_argument('--genesis', '-g', help='Genesis file', default='genesis.json')
args = parser.parse_args()
data_dir = args.datadir
if not data_dir:
data_dir = os.path.expanduser("~/eth_net_{}/".format(args.netid))
print("Using directory", data_dir)
passwd = data_dir+'password'
try:
os.makedirs(data_dir)
with open(passwd,'w') as f:
f.write('toto')
except Exception as e:
pass
print("Creating {} nodes.".format(args.nodes))
for x in range(0, args.nodes):
ddir = data_dir + "node{}".format(x)
try:
os.makedirs(ddir)
cmd = '{} --datadir {} --networkid "{}" --identity "Node{}" init {}'.format(args.geth, ddir, args.netid, x, args.genesis)
print(cmd)
proc.run(cmd, shell=True)
cmd = '{} --datadir {} --networkid "{}" --identity "Node{}" --password {} account new'.format(args.geth, ddir, args.netid, x, passwd)
print(cmd)
proc.run(cmd, shell=True)
except Exception as e:
print(e)
enode_finder = re.compile(b"enode://[0-9a-zA-Z]+@.+:\d+")
enodes = []
try:
for x in range(0, args.nodes):
ddir = data_dir + "node{}".format(x)
cmd = '{} --datadir {} --networkid "{}" --identity "Node{}" --port {} console'.format(args.geth, ddir, args.netid, x, args.start_port+x)
print(cmd)
with proc.Popen(cmd, shell=True, stdout=proc.PIPE, stderr=proc.PIPE) as p:
while True:
l = p.stderr.readline()
if l != '':
res = enode_finder.search(l);
if res:
enodes.append(res.group(0))
break
else:
break
except Exception as e:
print(e)
for enode in enodes:
print(enode)
bootnodes = b",".join(enodes).decode().replace('[::]', '[::1]')
ts = libtmux.Server()
screen_name = "eth{}".format(args.start_port)
print("Launching {} nodes in tmux session {}.".format(args.nodes, screen_name))
s = ts.new_session(screen_name)
for x in range(0, args.nodes):
nm = "node{}".format(x)
w = s.new_window(nm)
p = w.attached_pane
ddir = data_dir + nm
suppargs = ''
#if x >= args.nodes/2:
# suppargs += '--minerthreads "1" --mine '
if x == 0:
suppargs += '--rpc --rpcapi "personal,eth,net,web3" '
cmd = '{} --datadir {} -networkid "{}" --identity "{}" --port {} --bootnodes "{}" {} --verbosity "3" console'.format(args.geth, ddir, args.netid, nm, args.start_port+x, bootnodes, suppargs)
print(cmd)
p.send_keys(cmd)
time.sleep(1)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment