Commit cec89073 authored by Cédric Moreau's avatar Cédric Moreau

Now allow to sync with an existing keychain

parent 65f69d44
......@@ -260,6 +260,17 @@ function KeyHelper (packetList) {
return this.getHashedPackets(subkeys);
};
this.hasSubkey = function (keyID){
var matched = false;
(key.subKeys || []).forEach(function(subkeyWrapper){
if (subkeyWrapper.isValidSigningKey(key.primaryKey) || subkeyWrapper.isValidEncryptionKey(key.primaryKey)) {
if (subkeyWrapper.subKey.getFingerprint().toUpperCase().match(new RegExp(keyID + '$')))
matched = true;
}
});
return matched;
};
this.getHashedCertifPackets = function (){
var certifs = this.getBase64primaryUserOtherCertifications(); // Array of 1 packet lists (signature)
return this.getHashedPackets(certifs);
......
......@@ -22,14 +22,14 @@ module.exports = function Synchroniser (server, host, port, authenticated, conf)
var WalletService = server.WalletService;
var PeeringService = server.PeeringService;
var ParametersService = server.ParametersService;
var KeychainService = server.KeychainService;
// Models
var Amendment = server.conn.model('Amendment');
var PublicKey = server.conn.model('PublicKey');
var KeyBlock = server.conn.model('KeyBlock');
var Merkle = server.conn.model('Merkle');
var Key = server.conn.model('Key');
var Membership = server.conn.model('Membership');
var Voting = server.conn.model('Voting');
var Transaction = server.conn.model('Transaction');
var Wallet = server.conn.model('Wallet');
var Peer = server.conn.model('Peer');
......@@ -122,136 +122,152 @@ module.exports = function Synchroniser (server, host, port, authenticated, conf)
//============
// Parameters
//============
function (next){
node.registry.parameters(next);
},
function (params, next){
async.waterfall([
function (next){
Configuration.find({}, next);
},
function (confs, next){
var config = confs[0] || new Configuration();
var sync = _({}).extend(config.sync);
sync.AMStart = params.AMStart;
sync.AMFreq = params.AMFrequency;
sync.UDFreq = params.UDFrequency;
sync.UD0 = params.UD0;
sync.UDPercent = params.UDPercent;
sync.Consensus = params.Consensus;
config.sync = sync;
config.save(function (err) {
next(err);
});
},
], next);
},
// function (next){
// node.registry.parameters(next);
// },
// function (params, next){
// async.waterfall([
// function (next){
// Configuration.find({}, next);
// },
// function (confs, next){
// var config = confs[0] || new Configuration();
// var sync = _({}).extend(config.sync);
// sync.AMStart = params.AMStart;
// sync.AMFreq = params.AMFrequency;
// sync.UDFreq = params.UDFrequency;
// sync.UD0 = params.UD0;
// sync.UDPercent = params.UDPercent;
// sync.Consensus = params.Consensus;
// config.sync = sync;
// config.save(function (err) {
// next(err);
// });
// },
// ], next);
// },
//============
// Public Keys
//============
function (next){
Merkle.forPublicKeys(next);
},
function (merkle, next) {
node.pks.all({}, function (err, json) {
var rm = new NodesMerkle(json);
if(rm.root() != merkle.root()){
var leavesToAdd = [];
// Call with nice no to have PGP error 'gpg: input line longer than 19995 characters'
node.pks.all({ leaves: true, nice: true }, function (err, json) {
_(json.leaves).forEach(function(leaf){
if(merkle.leaves().indexOf(leaf) == -1){
leavesToAdd.push(leaf);
}
});
var hashes = [];
async.forEachSeries(leavesToAdd, function(leaf, callback){
logger.info('Importing public key %s...', leaf);
async.waterfall([
function (cb){
node.pks.all({ "leaf": leaf}, cb);
},
function (json, cb){
hashes.push(leaf);
PublicKey.persistFromRaw(json.leaf.value.pubkey, function (err) {
cb();
});
},
function (next) {
KeyService.handleKey(leaf, conf && conf.kmanagement == 'ALL', next);
},
], callback);
}, function(err, result){
next(err);
});
});
}
else next();
});
},
// function (next){
// Merkle.forPublicKeys(next);
// },
// function (merkle, next) {
// node.pks.all({}, function (err, json) {
// var rm = new NodesMerkle(json);
// if(rm.root() != merkle.root()){
// var leavesToAdd = [];
// // Call with nice no to have PGP error 'gpg: input line longer than 19995 characters'
// node.pks.all({ leaves: true, nice: true }, function (err, json) {
// _(json.leaves).forEach(function(leaf){
// if(merkle.leaves().indexOf(leaf) == -1){
// leavesToAdd.push(leaf);
// }
// });
// var hashes = [];
// async.forEachSeries(leavesToAdd, function(leaf, callback){
// logger.info('Importing public key %s...', leaf);
// async.waterfall([
// function (cb){
// node.pks.all({ "leaf": leaf}, cb);
// },
// function (json, cb){
// hashes.push(leaf);
// PublicKey.persistFromRaw(json.leaf.value.pubkey, function (err) {
// cb();
// });
// },
// function (next) {
// KeyService.handleKey(leaf, conf && conf.kmanagement == 'ALL', next);
// },
// ], callback);
// }, function(err, result){
// next(err);
// });
// });
// }
// else next();
// });
// },
//============
// Amendments
// Keychain
//============
function (next){
Amendment.nextNumber(next);
node.keychain.current(next);
},
function (number, next) {
node.hdc.amendments.current(function (err, json) {
if(err){
logger.warn('Issue getting current:');
err.split('\n').forEach(function (msg) {
logger.warn(msg);
function (current, next) {
KeychainService.checkWithLocalTimestamp = false;
var numbers = _.range(current.number + 1);
async.forEachSeries(numbers, function(number, callback){
async.waterfall([
function (next){
node.keychain.keyblock(number, next);
},
function (keyblock, next){
var block = new KeyBlock(keyblock);
console.log('keyblock#' + block.number, sha1(block.getRawSigned()));
var keyID = jpgp().signature(block.signature).issuer();
var newPubkeys = block.getNewPubkeys();
// Save pubkeys + block
async.waterfall([
function (next){
if (block.number == 0) {
var signatory = null;
newPubkeys.forEach(function(key){
if (key.hasSubkey(keyID))
signatory = key;
});
next();
if (!signatory) {
next('Root block signatory not found');
return;
}
remoteCurrentNumber = parseInt(json.number);
amendments[remoteCurrentNumber] = json.raw;
var toGetNumbers = _.range(number, remoteCurrentNumber + 1);
async.forEachSeries(toGetNumbers, function(amNumber, callback){
next(null, { fingerprint: signatory.getFingerprint(), raw: signatory.getArmored() });
} else {
PublicKey.getTheOne(keyID, next);
}
},
function (pubkey, next){
keyblock.pubkey = pubkey;
jpgp()
.publicKey(pubkey.raw)
.data(block.getRaw())
.signature(block.signature)
.verify(next);
},
function (verified, next){
async.forEach(newPubkeys, function(newPubkey, callback){
async.waterfall([
function (cb){
if(!amendments[amNumber])
node.hdc.amendments.promoted(amNumber, cb);
else
cb(null, { raw: amendments[amNumber] });
function (next){
parsers.parsePubkey(callback).asyncWrite(unix2dos(newPubkey.getArmored()), next);
},
function (am, cb){
amendments[amNumber] = am.raw;
node.hdc.amendments.promoted(amNumber, cb);
function (obj, next){
PublicKeyService.submitPubkey(obj, next);
},
function (am, cb){
amendments[amNumber] = am.raw;
cb();
], callback);
}, next);
},
function (cb) {
node.hdc.amendments.view.signatures(amNumber, sha1(amendments[amNumber]).toUpperCase(), { leaves: true }, cb);
function (next){
KeychainService.submitKeyBlock(keyblock, next);
},
function (json, cb){
applyVotes(amendments, amNumber, number, json, node, cb);
}
], function (err, result) {
callback(err);
});
}, function(err, result){
next(err);
});
});
], next);
},
], callback);
}, next)
},
//==============
// Transactions
//==============
function (next){
Key.find({ managed: true }, next);
},
function (keys, next) {
async.forEachSeries(keys, function (key, onKeyDone) {
syncTransactionsOfKey(node, key.fingerprint, onKeyDone);
}, next);
},
// function (next){
// Key.find({ managed: true }, next);
// },
// function (keys, next) {
// async.forEachSeries(keys, function (key, onKeyDone) {
// syncTransactionsOfKey(node, key.fingerprint, onKeyDone);
// }, next);
// },
//=========
// Wallets
......
......@@ -64,7 +64,7 @@ KeyBlockSchema.methods = {
[
"membersChanges",
].forEach(function(field){
json[field] = json[field] || [];
json[field] = that[field] || [];
});
[
"keysChanges",
......
......@@ -37,6 +37,10 @@ function KeyService (conn, conf, PublicKeyService, PeeringService) {
var Link = conn.model('Link');
var Key = conn.model('Key');
// Flag to say wether timestamp of received keyblocks should be tested
// Useful for synchronisation of old blocks
this.checkWithLocalTimestamp = true;
this.load = function (done) {
done();
};
......@@ -141,7 +145,7 @@ function KeyService (conn, conf, PublicKeyService, PeeringService) {
return;
}
// Test timestamp
if (Math.abs(block.timestamp - now.utcZero().timestamp()) > conf.tsInterval) {
if (KeychainService.checkWithLocalTimestamp && Math.abs(block.timestamp - now.utcZero().timestamp()) > conf.tsInterval) {
next('Timestamp does not match this node\'s time');
return;
}
......@@ -1472,6 +1476,7 @@ function KeyService (conn, conf, PublicKeyService, PeeringService) {
};
this.startGeneration = function (done) {
if (!conf.participate) return;
if (!PeeringService) {
done('Needed peering service activated.');
return;
......
......@@ -141,13 +141,15 @@ program
program
.command('sync [host] [port]')
.description('Tries to synchronise data with remote uCoin node')
.action(service(DO_NOT_LISTEN_HTTP, ucoin.createRegistryServer, function (host, port, server, conf) {
.action(service(DO_NOT_LISTEN_HTTP, ucoin.createPeerServer, function (host, port, server, conf) {
// Disable daemon
conf.sync.AMDaemon = "OFF";
conf.createNext = false;
// Stop keyblock generation
conf.participate = false;
async.series([
function (next) {
server.once('peerInited', next);
},
function (next){
// Synchronize
var Synchroniser = require('../app/lib/sync');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment