bip150: add authorized-peers and known-peers files.

This commit is contained in:
Christopher Jeffrey 2016-08-23 05:28:45 -07:00
parent 51975003c2
commit 799d3ba55d
No known key found for this signature in database
GPG Key ID: 8962AB9DE6666BBD
8 changed files with 190 additions and 15 deletions

View File

@ -36,8 +36,10 @@ index-address: false
headers: true headers: true
compact: true compact: true
bip151: true bip151: true
# bip150: false
# identity-key: 74b4147957813b62cc8987f2b711ddb31f8cb46dcbf71502033da66053c8780a
# proxy-server: localhost # proxy-server: localhost
# preferred-seed: # preferred-seed: seed.bitcoin.sipa.be
# ignore-discovery: false # ignore-discovery: false
# port: 8333 # port: 8333
listen: true listen: true
@ -54,6 +56,6 @@ listen: true
# ssl-key: /path/to/key # ssl-key: /path/to/key
# http-port: 8332 # http-port: 8332
# http-host: 0.0.0.0 # http-host: 0.0.0.0
# api-key: 74b4147957813b62cc8987f2b711ddb31f8cb46dcbf71502033da66053c8780a # api-key: foobar
# wallet-auth: true # wallet-auth: true
# no-auth: false # no-auth: false

View File

@ -290,15 +290,37 @@ function AuthDB() {
AuthDB.prototype.addKnown = function addKnown(host, key) { AuthDB.prototype.addKnown = function addKnown(host, key) {
assert(typeof host === 'string'); assert(typeof host === 'string');
assert(Buffer.isBuffer(key) && key.length === 33); assert(Buffer.isBuffer(key) && key.length === 33,
'Invalid public key for known peer.');
this.known[host] = key; this.known[host] = key;
}; };
AuthDB.prototype.setKnown = function setKnown(map) {
var keys = Object.keys(map);
var i, host, key;
for (i = 0; i < keys.length; i++) {
host = keys[i];
key = map[host];
this.addKnown(host, key);
}
};
AuthDB.prototype.addAuthorized = function addAuthorized(key) { AuthDB.prototype.addAuthorized = function addAuthorized(key) {
assert(Buffer.isBuffer(key) && key.length === 33); assert(Buffer.isBuffer(key) && key.length === 33,
'Invalid public key for authorized peer.');
this.auth.push(key); this.auth.push(key);
}; };
AuthDB.prototype.setAuthorized = function setAuthorized(auth) {
var i, key;
for (i = 0; i < auth.length; i++) {
key = auth[i];
this.addAuthorized(key);
}
};
AuthDB.prototype.getKnown = function getKnown(host) { AuthDB.prototype.getKnown = function getKnown(host) {
return this.known[host]; return this.known[host];
}; };

View File

@ -46,9 +46,8 @@ config.alias = {
config.parse = function parse(options) { config.parse = function parse(options) {
var env = {}; var env = {};
var arg = {}; var arg = {};
var text = {};
var data = {}; var data = {};
var prefix; var text, prefix;
if (!options) if (!options)
options = {}; options = {};
@ -70,11 +69,18 @@ config.parse = function parse(options) {
prefix = config.getPrefix(data); prefix = config.getPrefix(data);
text = config.parseFile(prefix + '/bcoin.conf'); text = config.parseFile(prefix + '/bcoin.conf');
} }
data = merge(text, data);
prefix = config.getPrefix(data);
if (!data.knownPeers)
data.knownPeers = config.parseKnown(prefix + '/known-peers');
if (!text.authPeers)
data.authPeers = config.parseAuth(prefix + '/authorized-peers');
} }
merge(text, data); return data;
return text;
}; };
/** /**
@ -151,6 +157,7 @@ config.parseData = function parseData(data) {
options.compact = bool(data.compact); options.compact = bool(data.compact);
options.bip151 = bool(data.bip151); options.bip151 = bool(data.bip151);
options.bip150 = bool(data.bip150); options.bip150 = bool(data.bip150);
options.identityKey = key(data.identitykey);
options.proxyServer = str(data.proxyserver); options.proxyServer = str(data.proxyserver);
options.preferredSeed = str(data.preferredseed); options.preferredSeed = str(data.preferredseed);
options.maxPeers = num(data.maxpeers); options.maxPeers = num(data.maxpeers);
@ -188,6 +195,26 @@ config.parseFile = function parseFile(file) {
return config.parseText(readFile(file)); return config.parseText(readFile(file));
}; };
/**
* Parse known peers file.
* @param {String} file
* @returns {Object}
*/
config.parseKnown = function parseKnown(file) {
return config.parseKnownText(readFile(file));
};
/**
* Parse authorized peers file.
* @param {String} file
* @returns {Object}
*/
config.parseAuth = function parseAuth(file) {
return config.parseAuthText(readFile(file));
};
/** /**
* Parse config text. * Parse config text.
* @param {String} text * @param {String} text
@ -359,6 +386,86 @@ config.parseEnv = function parseEnv(env) {
return config.parseData(data); return config.parseData(data);
}; };
/**
* Parse known peers.
* @param {String} text
* @returns {Object}
*/
config.parseKnownText = function parseKnownText(text) {
var lines = text.split(/\n+/);
var map = {};
var i, line, parts, hostname, host, ip, key;
for (i = 0; i < lines.length; i++) {
line = lines[i].trim();
if (line.length === 0)
continue;
if (/^\s*#/.test(line))
continue;
parts = line.split(/\s+/);
if (parts.length < 2)
continue;
hostname = parts[0].trim().split(',');
if (hostname.length >= 2) {
host = hostname[0];
ip = hostname[1];
} else {
ip = hostname[0];
}
key = parts[1].trim();
key = new Buffer(key, 'hex');
if (key.length !== 33)
throw new Error('Invalid key: ' + parts[1]);
if (host)
map[host] = key;
map[ip] = key;
}
return map;
};
/**
* Parse authorized peers.
* @param {String} text
* @returns {Buffer[]} keys
*/
config.parseAuthText = function parseAuthText(text) {
var lines = text.split(/\n+/);
var keys = [];
var i, line, key;
for (i = 0; i < lines.length; i++) {
line = lines[i].trim();
if (line.length === 0)
continue;
if (/^\s*#/.test(line))
continue;
key = new Buffer(line, 'hex');
if (key.length !== 33)
throw new Error('Invalid key: ' + line);
keys.push(key);
}
return keys;
};
/* /*
* Helpers * Helpers
*/ */
@ -369,6 +476,23 @@ function str(value) {
return value; return value;
} }
function key(value) {
var key;
if (!value)
return null;
if (typeof value !== 'string')
return null;
key = new Buffer(value, 'hex');
if (key.length !== 32)
throw new Error('Invalid key: ' + value);
return key;
}
function path(value) { function path(value) {
if (!value) if (!value)
return null; return null;
@ -447,6 +571,8 @@ function merge(a, b) {
if (b[key] != null) if (b[key] != null)
a[key] = b[key]; a[key] = b[key];
} }
return a;
} }
/* /*

View File

@ -357,6 +357,9 @@ ec.privateKeyVerify = function privateKeyVerify(key) {
if (secp256k1) if (secp256k1)
return secp256k1.privateKeyVerify(key); return secp256k1.privateKeyVerify(key);
if (key.length !== 32)
return false;
key = new bn(key); key = new bn(key);
return key.cmpn(0) !== 0 && key.cmp(ec.elliptic.curve.n) < 0; return key.cmpn(0) !== 0 && key.cmp(ec.elliptic.curve.n) < 0;

View File

@ -101,8 +101,9 @@ function Fullnode(options) {
compact: this.options.compact, compact: this.options.compact,
bip151: this.options.bip151, bip151: this.options.bip151,
bip150: this.options.bip150, bip150: this.options.bip150,
auth: this.options.auth, authPeers: this.options.authPeers,
identity: this.options.identity, knownPeers: this.options.knownPeers,
identityKey: this.options.identityKey,
maxPeers: this.options.maxPeers, maxPeers: this.options.maxPeers,
maxLeeches: this.options.maxLeeches, maxLeeches: this.options.maxLeeches,
proxyServer: this.options.proxyServer, proxyServer: this.options.proxyServer,

View File

@ -148,7 +148,7 @@ function Peer(pool, options) {
this.hostname, this.hostname,
this.type !== Peer.types.LEECH, this.type !== Peer.types.LEECH,
this.pool.auth, this.pool.auth,
this.pool.identity); this.pool.identityKey);
this.bip151.bip150 = this.bip150; this.bip151.bip150 = this.bip150;
} }
} }

View File

@ -147,12 +147,23 @@ function Pool(options) {
this.locker = new bcoin.locker(this); this.locker = new bcoin.locker(this);
this.proxyServer = options.proxyServer; this.proxyServer = options.proxyServer;
this.auth = null; this.auth = null;
this.identity = null; this.identityKey = null;
if (this.options.bip150) { if (this.options.bip150) {
this.options.bip151 = true; this.options.bip151 = true;
this.auth = options.auth || new bcoin.bip150.AuthDB(); this.auth = new bcoin.bip150.AuthDB();
this.identity = options.identity || bcoin.ec.generatePrivateKey();
if (options.authPeers)
this.auth.setAuthorized(options.authPeers);
if (options.knownPeers)
this.auth.setKnown(options.knownPeers);
this.identityKey = options.identityKey || bcoin.ec.generatePrivateKey();
assert(Buffer.isBuffer(this.identityKey), 'Identity key must be a buffer.');
assert(bcoin.ec.privateKeyVerify(this.identityKey),
'Invalid identity key.');
} }
this.syncing = false; this.syncing = false;
@ -341,6 +352,11 @@ Pool.prototype._open = function _open(callback) {
self.logger.info('Pool loaded (maxpeers=%d).', self.maxPeers); self.logger.info('Pool loaded (maxpeers=%d).', self.maxPeers);
if (self.identityKey) {
self.logger.info('Identity public key: %s',
bcoin.ec.publicKeyCreate(self.identityKey, true).toString('hex'));
}
if (!self.options.listen) if (!self.options.listen)
return callback(); return callback();

View File

@ -58,6 +58,11 @@ function SPVNode(options) {
witness: this.options.witness, witness: this.options.witness,
proxyServer: this.options.proxyServer, proxyServer: this.options.proxyServer,
preferredSeed: this.options.preferredSeed, preferredSeed: this.options.preferredSeed,
bip151: this.options.bip151,
bip150: this.options.bip150,
authPeers: this.options.authPeers,
knownPeers: this.options.knownPeers,
identityKey: this.options.identityKey,
maxPeers: this.options.maxPeers, maxPeers: this.options.maxPeers,
ignoreDiscovery: this.options.ignoreDiscovery, ignoreDiscovery: this.options.ignoreDiscovery,
selfish: true, selfish: true,