From cec890739b26e00c57f977212d35e50d8899742f Mon Sep 17 00:00:00 2001 From: cgeek <cem.moreau@gmail.com> Date: Tue, 26 Aug 2014 21:21:06 +0200 Subject: [PATCH] Now allow to sync with an existing keychain --- app/lib/keyhelper.js | 11 ++ app/lib/sync.js | 264 +++++++++++++++++---------------- app/models/keyblock.js | 2 +- app/service/KeychainService.js | 7 +- bin/ucoind | 10 +- 5 files changed, 164 insertions(+), 130 deletions(-) diff --git a/app/lib/keyhelper.js b/app/lib/keyhelper.js index 9b908e2ef..e418fe8ed 100644 --- a/app/lib/keyhelper.js +++ b/app/lib/keyhelper.js @@ -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); diff --git a/app/lib/sync.js b/app/lib/sync.js index 5c9c8d754..41ef516b4 100644 --- a/app/lib/sync.js +++ b/app/lib/sync.js @@ -16,20 +16,20 @@ module.exports = function Synchroniser (server, host, port, authenticated, conf) var that = this; // Services - var PublicKeyService = server.PublicKeyService; - var KeyService = server.KeyService; - var TransactionService = server.TransactionsService; - var WalletService = server.WalletService; - var PeeringService = server.PeeringService; - var ParametersService = server.ParametersService; + var PublicKeyService = server.PublicKeyService; + var KeyService = server.KeyService; + var TransactionService = server.TransactionsService; + 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); - }); - next(); - return; - } - remoteCurrentNumber = parseInt(json.number); - amendments[remoteCurrentNumber] = json.raw; - var toGetNumbers = _.range(number, remoteCurrentNumber + 1); - async.forEachSeries(toGetNumbers, function(amNumber, callback){ - async.waterfall([ - function (cb){ - if(!amendments[amNumber]) - node.hdc.amendments.promoted(amNumber, cb); - else - cb(null, { raw: amendments[amNumber] }); - }, - function (am, cb){ - amendments[amNumber] = am.raw; - node.hdc.amendments.promoted(amNumber, cb); - }, - function (am, cb){ - amendments[amNumber] = am.raw; - cb(); - }, - function (cb) { - node.hdc.amendments.view.signatures(amNumber, sha1(amendments[amNumber]).toUpperCase(), { leaves: true }, cb); - }, - function (json, cb){ - applyVotes(amendments, amNumber, number, json, node, cb); - } - ], function (err, result) { - callback(err); - }); - }, function(err, result){ - next(err); - }); - }); + 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; + }); + if (!signatory) { + next('Root block signatory not found'); + return; + } + 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 (next){ + parsers.parsePubkey(callback).asyncWrite(unix2dos(newPubkey.getArmored()), next); + }, + function (obj, next){ + PublicKeyService.submitPubkey(obj, next); + }, + ], callback); + }, next); + }, + function (next){ + KeychainService.submitKeyBlock(keyblock, next); + }, + ], 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 diff --git a/app/models/keyblock.js b/app/models/keyblock.js index 3205be1db..a5ef62fda 100644 --- a/app/models/keyblock.js +++ b/app/models/keyblock.js @@ -64,7 +64,7 @@ KeyBlockSchema.methods = { [ "membersChanges", ].forEach(function(field){ - json[field] = json[field] || []; + json[field] = that[field] || []; }); [ "keysChanges", diff --git a/app/service/KeychainService.js b/app/service/KeychainService.js index 9408b71fe..77eddf039 100644 --- a/app/service/KeychainService.js +++ b/app/service/KeychainService.js @@ -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; diff --git a/bin/ucoind b/bin/ucoind index 84dc818b2..1aabb84ec 100755 --- a/bin/ucoind +++ b/bin/ucoind @@ -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'); -- GitLab