|
|
@ -999,14 +999,13 @@ var handleMessage = ChainPad.handleMessage = function (realtime, msgStr) {
|
|
|
|
&& Common.strcmp(realtime.best.hashOf, msg.hashOf) > 0))
|
|
|
|
&& Common.strcmp(realtime.best.hashOf, msg.hashOf) > 0))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// switch chains
|
|
|
|
// switch chains
|
|
|
|
debug(realtime, "Patch [" + msg.hashOf + "] is best, switching chains.");
|
|
|
|
|
|
|
|
while (commonAncestor && !isAncestorOf(realtime, commonAncestor, msg)) {
|
|
|
|
while (commonAncestor && !isAncestorOf(realtime, commonAncestor, msg)) {
|
|
|
|
toRevert.push(commonAncestor);
|
|
|
|
toRevert.push(commonAncestor);
|
|
|
|
commonAncestor = getParent(realtime, commonAncestor);
|
|
|
|
commonAncestor = getParent(realtime, commonAncestor);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Common.assert(commonAncestor);
|
|
|
|
Common.assert(commonAncestor);
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
debug(realtime, "Patch [" + msg.hashOf + "] chain not best, staying.");
|
|
|
|
debug(realtime, "Patch [" + msg.hashOf + "] chain is ["+pcMsg+"] best chain is ["+pcBest+"]");
|
|
|
|
if (Common.PARANOIA) { check(realtime); }
|
|
|
|
if (Common.PARANOIA) { check(realtime); }
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1026,16 +1025,10 @@ var handleMessage = ChainPad.handleMessage = function (realtime, msgStr) {
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < toRevert.length; i++) {
|
|
|
|
for (var i = 0; i < toRevert.length; i++) {
|
|
|
|
authDocAtTimeOfPatch = Patch.apply(toRevert[i].content.inverseOf, authDocAtTimeOfPatch);
|
|
|
|
authDocAtTimeOfPatch = Patch.apply(toRevert[i].content.inverseOf, authDocAtTimeOfPatch);
|
|
|
|
if (Common.PARANOIA) {
|
|
|
|
|
|
|
|
Common.assert(Sha.hex_sha256(authDocAtTimeOfPatch) === toRevert[i].content.parentHash);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// toApply.length-1 because we do not want to apply the new patch.
|
|
|
|
// toApply.length-1 because we do not want to apply the new patch.
|
|
|
|
for (var i = 0; i < toApply.length-1; i++) {
|
|
|
|
for (var i = 0; i < toApply.length-1; i++) {
|
|
|
|
if (Common.PARANOIA) {
|
|
|
|
|
|
|
|
Common.assert(Sha.hex_sha256(authDocAtTimeOfPatch) === toApply[i].content.parentHash);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (typeof(toApply[i].content.inverseOf) === 'undefined') {
|
|
|
|
if (typeof(toApply[i].content.inverseOf) === 'undefined') {
|
|
|
|
toApply[i].content.inverseOf = Patch.invert(toApply[i].content, authDocAtTimeOfPatch);
|
|
|
|
toApply[i].content.inverseOf = Patch.invert(toApply[i].content, authDocAtTimeOfPatch);
|
|
|
|
toApply[i].content.inverseOf.inverseOf = toApply[i].content;
|
|
|
|
toApply[i].content.inverseOf.inverseOf = toApply[i].content;
|
|
|
@ -1043,18 +1036,13 @@ var handleMessage = ChainPad.handleMessage = function (realtime, msgStr) {
|
|
|
|
authDocAtTimeOfPatch = Patch.apply(toApply[i].content, authDocAtTimeOfPatch);
|
|
|
|
authDocAtTimeOfPatch = Patch.apply(toApply[i].content, authDocAtTimeOfPatch);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var authDocHashAtTimeOfPatch = Sha.hex_sha256(authDocAtTimeOfPatch);
|
|
|
|
if (Sha.hex_sha256(authDocAtTimeOfPatch) !== patch.parentHash) {
|
|
|
|
if (authDocHashAtTimeOfPatch !== patch.parentHash) {
|
|
|
|
|
|
|
|
debug(realtime, "patch [" + msg.hashOf + "] parentHash is not valid");
|
|
|
|
debug(realtime, "patch [" + msg.hashOf + "] parentHash is not valid");
|
|
|
|
if (Common.PARANOIA) { check(realtime); }
|
|
|
|
if (Common.PARANOIA) { check(realtime); }
|
|
|
|
//delete realtime.messages[msg.hashOf];
|
|
|
|
if (Common.TESTING) { throw new Error(); }
|
|
|
|
|
|
|
|
delete realtime.messages[msg.hashOf];
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (authDocAtTimeOfPatch === realtime.authDoc &&
|
|
|
|
|
|
|
|
authDocHashAtTimeOfPatch !== realtime.best.inverseOf.parentHash)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
throw new Error("authDoc does not match chain head");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var simplePatch =
|
|
|
|
var simplePatch =
|
|
|
|
Patch.simplify(patch, authDocAtTimeOfPatch, realtime.config.operationSimplify);
|
|
|
|
Patch.simplify(patch, authDocAtTimeOfPatch, realtime.config.operationSimplify);
|
|
|
@ -1175,7 +1163,6 @@ module.exports.create = function (userName, authToken, channelId, initialState,
|
|
|
|
Common.assert(typeof(initialState) === 'string');
|
|
|
|
Common.assert(typeof(initialState) === 'string');
|
|
|
|
var realtime = ChainPad.create(userName, authToken, channelId, initialState, conf);
|
|
|
|
var realtime = ChainPad.create(userName, authToken, channelId, initialState, conf);
|
|
|
|
return {
|
|
|
|
return {
|
|
|
|
Sha: Sha,
|
|
|
|
|
|
|
|
onPatch: enterChainPad(realtime, function (handler) {
|
|
|
|
onPatch: enterChainPad(realtime, function (handler) {
|
|
|
|
Common.assert(typeof(handler) === 'function');
|
|
|
|
Common.assert(typeof(handler) === 'function');
|
|
|
|
realtime.patchHandlers.push(handler);
|
|
|
|
realtime.patchHandlers.push(handler);
|
|
|
|