diff --git a/app/models/certification.js b/app/models/certification.js index 6f618ecdfe570e6dd95a7e80ac1bdb5c10104fc9..0bda45725762b99e0968ace43845beabf49b002e 100644 --- a/app/models/certification.js +++ b/app/models/certification.js @@ -15,6 +15,7 @@ var CertificationSchema = new Schema({ time: { type: Date, default: Date.now }, target: String, to: String, + linked: { type: Boolean, default: false }, created: { type: Date, default: Date.now }, updated: { type: Date, default: Date.now } }); @@ -34,9 +35,9 @@ CertificationSchema.virtual('when').get(function () { CertificationSchema.methods = { - exists: function (done) { + existing: function (done) { this.model('Certification').find({ "pubkey": this.pubkey, "sig": this.sig, "time": this.time, "target": this.target }, function (err, certs) { - done(err, certs && certs.length > 0); + done(err, certs && certs.length > 0 ? certs[0] : null); }); }, @@ -77,4 +78,11 @@ CertificationSchema.statics.from = function (pubkey, done) { }); }; +CertificationSchema.statics.findNew = function (done) { + var Certification = this.model('Certification'); + Certification.find({ "linked": false }, function (err, certs) { + done(err, certs); + }); +}; + module.exports = CertificationSchema; diff --git a/app/models/identity.js b/app/models/identity.js index b3497f7fdc98a22f20c69efe7866fc4d061d9a17..ecab6b5c8b530097bc323f4e79ebbb0d26cfd49a 100644 --- a/app/models/identity.js +++ b/app/models/identity.js @@ -144,6 +144,13 @@ IdentitySchema.statics.isMember = function(pubkey, done){ }); } +IdentitySchema.statics.isMemberOrError = function(pubkey, done){ + var Identity = this.model('Identity'); + Identity.isMember(pubkey, function (err, isMember) { + done(err || (!isMember && "Not a member")); + }); +} + IdentitySchema.statics.getMember = function(pubkey, done){ var Identity = this.model('Identity'); Identity.find({ "pubkey": pubkey, "member": true }, function (err, identities) { diff --git a/app/service/BlockchainService.js b/app/service/BlockchainService.js index 54ff5112106294a9e0a2c7931bcdf828072333f0..f9c1e95dc4240e7506408985b9d98d61668614df 100644 --- a/app/service/BlockchainService.js +++ b/app/service/BlockchainService.js @@ -317,16 +317,16 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { }, function (idty, next){ cert.target = idty.getTargetHash(); - cert.exists(next); + cert.existing(next); }, - function (exists, next) { - if (exists) { - next(); - } else { - cert.save(function (err) { - next(err); - }); + function (existing, next) { + if (existing) { + cert = existing; } + cert.linked = true; + cert.save(function (err) { + next(err); + }); } ], callback); }, done); @@ -508,23 +508,49 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { function (next){ findUpdates(next); }, - function (updates, subupdates, next){ + function (updates, next){ Block.current(function (err, current) { - next(null, current || null, updates, subupdates); + next(null, current || null, updates); }); }, - function (current, updates, subupdates, next){ - createNewcomerBlock(current, null, {}, updates, subupdates, next); + function (current, updates, next){ + createNewcomerBlock(current, null, {}, updates, next); }, ], done); } function findUpdates (done) { var updates = {}; - var subupdates = {}; done(null, [], []); // TODO: certifications - // updates[pubkey] = certifications; + async.waterfall([ + function (next){ + Certification.findNew(next); + }, + function (certs, next){ + async.forEachSeries(certs, function(cert, callback){ + async.waterfall([ + function (next){ + // Signatory must be a member + Identity.isMemberOrError(cert.from, next); + }, + function (next){ + // Certified must be a member + Identity.isMemberOrError(cert.to, next); + }, + function (next){ + updates[cert.to] = updates[cert.to] || []; + updates[cert.to].push(cert); + next(); + }, + ], function (err) { + callback(); + }); + }, next); + }, + ], function (err) { + done(err, updates); + }); } /** @@ -605,7 +631,9 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { * Generate a "newcomers" keyblock */ this.generateNewcomersBlock = function (filteringFunc, checkingWoTFunc, done) { - var withoutUpdates = function(updates) { updates(null, {}, {}); }; + var withoutUpdates = function(updatesDone) { + updatesDone(null, {}); + }; KeychainService.generateNextBlock(withoutUpdates, filteringFunc, checkingWoTFunc, done); }; @@ -614,7 +642,6 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { */ this.generateNextBlock = function (findUpdateFunc, filteringFunc, checkingWoTFunc, done) { var updates = {}; - var subupdates = {}; async.waterfall([ function (next) { // First, check for members' key updates @@ -622,7 +649,6 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { }, function (theUpdates, theSubupdates, next) { updates = theUpdates; - subupdates = theSubupdates; findNewcomers(filteringFunc, checkingWoTFunc, next); }, function (current, newWoT, joinData, otherUpdates, next){ @@ -631,10 +657,10 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { if (!updates[fpr]) updates[fpr] = otherUpdates[fpr]; else - updates[fpr].concat(otherUpdates[fpr]); + updates[fpr] = updates[fpr].concat(otherUpdates[fpr]); }); // Create the block - createNewcomerBlock(current, joinData, updates, subupdates, next); + createNewcomerBlock(current, joinData, updates, next); }, ], done); }; @@ -805,7 +831,6 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { } function findSignaturesFromNewcomerToWoT (newcomer, done) { - var updates = {}; async.waterfall([ function (next){ @@ -844,7 +869,7 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { return matched; } - function createNewcomerBlock (current, joinData, updates, subupdates, done) { + function createNewcomerBlock (current, joinData, updates, done) { var block = new Block(); block.version = 1; block.currency = current ? current.currency : conf.currency; @@ -880,7 +905,7 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { block.leavers = []; // Kicked people block.excluded = []; - // Certifications FROM the WoT + // Certifications from the WoT, to newcomers block.certifications = []; joiners.forEach(function(joiner){ var data = joinData[joiner]; @@ -888,7 +913,7 @@ function BlockchainService (conn, conf, IdentityService, PeeringService) { block.certifications.push(cert.inline()); }); }); - // Certifications TO the WoT + // Certifications from the WoT, to the WoT _(updates).keys().forEach(function(certifiedMember){ var certs = updates[certifiedMember]; certs.forEach(function(cert){ diff --git a/app/service/IdentityService.js b/app/service/IdentityService.js index 7a44c22749d5636a2afa58fc3d9110948887ccae..f50efdcb36fa680446cc46f676dbc5488629d106 100644 --- a/app/service/IdentityService.js +++ b/app/service/IdentityService.js @@ -54,10 +54,10 @@ function IdentityService (conn, conf) { var mCert = new Certification({ pubkey: cert.from, sig: cert.sig, time: cert.time, target: obj.hash, to: idty.pubkey }); async.waterfall([ function (next){ - mCert.exists(next); + mCert.existing(next); }, - function (exists, next){ - if (exists) next(); + function (existing, next){ + if (existing) next(); else mCert.save(function (err) { next(err); });