update block storage APIs

pull/1/head
ansuz 4 years ago
parent 15a8284a30
commit 729d51fb9b

@ -392,7 +392,7 @@ define([
// send an RPC to store the block which you created. // send an RPC to store the block which you created.
console.log("initializing rpc interface"); console.log("initializing rpc interface");
Pinpad.create(RT.network, RT.proxy, waitFor(function (e, _rpc) { Pinpad.create(RT.network, Block.keysToRPCFormat(res.opt.blockKeys), waitFor(function (e, _rpc) {
if (e) { if (e) {
waitFor.abort(); waitFor.abort();
console.error(e); // INVALID_KEYS console.error(e); // INVALID_KEYS

@ -86,7 +86,7 @@ var createLoginBlockPath = function (Env, publicKey) { // FIXME BLOCKS
return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey); return Path.join(Env.paths.block, safeKey.slice(0, 2), safeKey);
}; };
var validateAncestorProof = function (Env, proof, _cb) { Block.validateAncestorProof = function (Env, proof, _cb) {
var cb = Util.once(Util.mkAsync(_cb)); var cb = Util.once(Util.mkAsync(_cb));
/* prove that you own an existing block by signing for its publicKey */ /* prove that you own an existing block by signing for its publicKey */
try { try {
@ -97,7 +97,6 @@ var validateAncestorProof = function (Env, proof, _cb) {
var u8_sig = Nacl.util.decodeBase64(sig); var u8_sig = Nacl.util.decodeBase64(sig);
var valid = false; var valid = false;
nThen(function (w) { nThen(function (w) {
// XXX restricted-registration do this in a worker
valid = Nacl.sign.detached.verify(u8_pub, u8_sig, u8_pub); valid = Nacl.sign.detached.verify(u8_pub, u8_sig, u8_pub);
if (!valid) { if (!valid) {
w.abort(); w.abort();
@ -130,14 +129,23 @@ Block.writeLoginBlock = function (Env, safeKey, msg, _cb) { // FIXME BLOCKS
var validatedBlock, parsed, path; var validatedBlock, parsed, path;
nThen(function (w) { nThen(function (w) {
if (Util.escapeKeyCharacters(publicKey) !== safeKey) {
w.abort();
return void cb("INCORRECT_KEY");
}
}).nThen(function (w) {
if (!Env.restrictRegistration) { return; } if (!Env.restrictRegistration) { return; }
if (!registrationProof) { if (!registrationProof) {
// we allow users with existing blocks to create new ones // we allow users with existing blocks to create new ones
// call back with error if registration is restricted and no proof of an existing block was provided // call back with error if registration is restricted and no proof of an existing block was provided
w.abort(); w.abort();
Env.Log.info("BLOCK_REJECTED_REGISTRATION", {
safeKey: safeKey,
publicKey: publicKey,
});
return cb("E_RESTRICTED"); return cb("E_RESTRICTED");
} }
validateAncestorProof(Env, registrationProof, w(function (err, provenKey) { Env.validateAncestorProof(registrationProof, w(function (err, provenKey) {
if (err || !provenKey) { // double check that a key was validated if (err || !provenKey) { // double check that a key was validated
w.abort(); w.abort();
Env.Log.warn('BLOCK_REJECTED_INVALID_ANCESTOR', { Env.Log.warn('BLOCK_REJECTED_INVALID_ANCESTOR', {
@ -191,6 +199,7 @@ Block.writeLoginBlock = function (Env, safeKey, msg, _cb) { // FIXME BLOCKS
blockId: publicKey, blockId: publicKey,
isChange: Boolean(registrationProof), isChange: Boolean(registrationProof),
previousKey: previousKey, previousKey: previousKey,
path: path,
}); });
cb(); cb();
}); });
@ -212,26 +221,33 @@ Block.removeLoginBlock = function (Env, safeKey, msg, cb) { // FIXME BLOCKS
var signature = msg[1]; var signature = msg[1];
var block = Nacl.util.decodeUTF8('DELETE_BLOCK'); // clients and the server will have to agree on this constant var block = Nacl.util.decodeUTF8('DELETE_BLOCK'); // clients and the server will have to agree on this constant
validateLoginBlock(Env, publicKey, signature, block, function (e /*::, validatedBlock */) { nThen(function (w) {
if (e) { return void cb(e); } if (Util.escapeKeyCharacters(publicKey) !== safeKey) {
// derive the filepath w.abort();
var path = createLoginBlockPath(Env, publicKey); return void cb("INCORRECT_KEY");
// make sure the path is valid
if (typeof(path) !== 'string') {
return void cb('E_INVALID_BLOCK_PATH');
} }
}).nThen(function () {
validateLoginBlock(Env, publicKey, signature, block, function (e /*::, validatedBlock */) {
if (e) { return void cb(e); }
// derive the filepath
var path = createLoginBlockPath(Env, publicKey);
// FIXME COLDSTORAGE // make sure the path is valid
Fs.unlink(path, function (err) { if (typeof(path) !== 'string') {
Env.Log.info('DELETION_BLOCK_BY_OWNER_RPC', { return void cb('E_INVALID_BLOCK_PATH');
publicKey: publicKey, }
path: path,
status: err? String(err): 'SUCCESS',
});
if (err) { return void cb(err); } // FIXME COLDSTORAGE
cb(); Fs.unlink(path, function (err) {
Env.Log.info('DELETION_BLOCK_BY_OWNER_RPC', {
publicKey: publicKey,
path: path,
status: err? String(err): 'SUCCESS',
});
if (err) { return void cb(err); }
cb();
});
}); });
}); });
}; };

@ -158,6 +158,7 @@ module.exports.create = function (Env, cb) {
pinPath: Env.paths.pin, pinPath: Env.paths.pin,
filePath: Env.paths.data, filePath: Env.paths.data,
archivePath: Env.paths.archive, archivePath: Env.paths.archive,
blockPath: Env.paths.block,
inactiveTime: Env.inactiveTime, inactiveTime: Env.inactiveTime,
archiveRetentionTime: Env.archiveRetentionTime, archiveRetentionTime: Env.archiveRetentionTime,

@ -295,7 +295,7 @@ var owned_upload_complete = function (Env, safeKey, id, cb) {
// removeBlob // removeBlob
var remove = function (Env, blobId, cb) { var remove = function (Env, blobId, cb) {
var blobPath = makeBlobPath(Env, blobId); var blobPath = makeBlobPath(Env, blobId);
Fs.unlink(blobPath, cb); // TODO COLDSTORAGE Fs.unlink(blobPath, cb);
}; };
// removeProof // removeProof

@ -4,6 +4,7 @@
const HK = require("../hk-util"); const HK = require("../hk-util");
const Store = require("../storage/file"); const Store = require("../storage/file");
const BlobStore = require("../storage/blob"); const BlobStore = require("../storage/blob");
const Block = require("../commands/block");
const Util = require("../common-util"); const Util = require("../common-util");
const nThen = require("nthen"); const nThen = require("nthen");
const Meta = require("../metadata"); const Meta = require("../metadata");
@ -47,6 +48,7 @@ const init = function (config, _cb) {
Env.paths = { Env.paths = {
pin: config.pinPath, pin: config.pinPath,
block: config.blockPath,
}; };
Env.inactiveTime = config.inactiveTime; Env.inactiveTime = config.inactiveTime;
@ -688,6 +690,10 @@ COMMANDS.HASH_CHANNEL_LIST = function (data, cb) {
cb(void 0, hash); cb(void 0, hash);
}; };
COMMANDS.VALIDATE_ANCESTOR_PROOF = function (data, cb) {
Block.validateAncestorProof(Env, data && data.proof, cb);
};
process.on('message', function (data) { process.on('message', function (data) {
if (!data || !data.txid || !data.pid) { if (!data || !data.txid || !data.pid) {
return void process.send({ return void process.send({

@ -444,6 +444,13 @@ Workers.initialize = function (Env, config, _cb) {
}, cb); }, cb);
}; };
Env.validateAncestorProof = function (proof, cb) {
sendCommand({
command: 'VALIDATE_ANCESTOR_PROOF',
proof: proof,
}, cb);
};
cb(void 0); cb(void 0);
}); });
}; };

@ -1735,6 +1735,7 @@ define([
var removeData = obj.Block.remove(blockKeys); var removeData = obj.Block.remove(blockKeys);
postMessage("DELETE_ACCOUNT", { postMessage("DELETE_ACCOUNT", {
keys: Block.keysToRPCFormat(blockKeys),
removeData: removeData removeData: removeData
}, function (obj) { }, function (obj) {
if (obj.state) { if (obj.state) {
@ -1856,11 +1857,15 @@ define([
var content = Block.serialize(JSON.stringify(temp), blockKeys); var content = Block.serialize(JSON.stringify(temp), blockKeys);
console.error("OLD AND NEW BLOCK KEYS", oldBlockKeys, blockKeys); console.error("OLD AND NEW BLOCK KEYS", oldBlockKeys, blockKeys);
// XXX ignored unless restricted registration is active?
content.registrationProof = Block.proveAncestor(oldBlockKeys); content.registrationProof = Block.proveAncestor(oldBlockKeys);
console.log("writing new login block"); console.log("writing new login block");
common.writeLoginBlock(content, waitFor(function (obj) {
var data = {
keys: Block.keysToRPCFormat(blockKeys),
content: content,
};
common.writeLoginBlock(data, waitFor(function (obj) {
if (obj && obj.error) { if (obj && obj.error) {
waitFor.abort(); waitFor.abort();
return void cb(obj); return void cb(obj);
@ -1878,8 +1883,11 @@ define([
// Remove block hash // Remove block hash
if (blockHash) { if (blockHash) {
console.log('removing old login block'); console.log('removing old login block');
var removeData = Block.remove(oldBlockKeys); var data = {
common.removeLoginBlock(removeData, waitFor(function (obj) { keys: Block.keysToRPCFormat(oldBlockKeys), // { edPrivate, edPublic }
content: Block.remove(oldBlockKeys),
};
common.removeLoginBlock(data, waitFor(function (obj) {
if (obj && obj.error) { return void console.error(obj.error); } if (obj && obj.error) { return void console.error(obj.error); }
})); }));
} }

@ -451,19 +451,33 @@ define([
}; };
Store.writeLoginBlock = function (clientId, data, cb) { Store.writeLoginBlock = function (clientId, data, cb) {
store.rpc.writeLoginBlock(data, function (e, res) { Pinpad.create(store.network, data && data.keys, function (err, rpc) {
cb({ if (err) {
error: e, return void cb({
data: res error: err,
});
}
rpc.writeLoginBlock(data && data.content, function (e, res) {
cb({
error: e,
data: res
});
}); });
}); });
}; };
Store.removeLoginBlock = function (clientId, data, cb) { Store.removeLoginBlock = function (clientId, data, cb) {
store.rpc.removeLoginBlock(data, function (e, res) { Pinpad.create(store.network, data && data.keys, function (err, rpc) {
cb({ if (err) {
error: e, return void cb({
data: res error: err,
});
}
rpc.removeLoginBlock(data && data.content, function (e, res) {
cb({
error: e,
data: res
});
}); });
}); });
}; };
@ -815,6 +829,7 @@ define([
Store.deleteAccount = function (clientId, data, cb) { Store.deleteAccount = function (clientId, data, cb) {
var edPublic = store.proxy.edPublic; var edPublic = store.proxy.edPublic;
var removeData = data && data.removeData; var removeData = data && data.removeData;
var rpcKeys = data && data.keys;
Store.anonRpcMsg(clientId, { Store.anonRpcMsg(clientId, {
msg: 'GET_METADATA', msg: 'GET_METADATA',
data: store.driveChannel data: store.driveChannel
@ -845,8 +860,15 @@ define([
}, waitFor()); }, waitFor());
}).nThen(function (waitFor) { }).nThen(function (waitFor) {
if (!removeData) { return; } if (!removeData) { return; }
// Delete the block. Don't abort if it fails, it doesn't leak any data. var done = waitFor();
store.rpc.removeLoginBlock(removeData, waitFor()); Pinpad.create(store.network, rpcKeys, function (err, rpc) {
if (err) {
console.error(err);
return void done();
}
// Delete the block. Don't abort if it fails, it doesn't leak any data.
rpc.removeLoginBlock(removeData, done);
});
}).nThen(function () { }).nThen(function () {
// Log out current worker // Log out current worker
postMessage(clientId, "DELETE_ACCOUNT", token, function () {}); postMessage(clientId, "DELETE_ACCOUNT", token, function () {});

@ -40,6 +40,19 @@ define([
}; };
}; };
Block.keysToRPCFormat = function (keys) {
try {
var sign = keys.sign;
return {
edPrivate: Nacl.util.encodeBase64(sign.secretKey),
edPublic: Nacl.util.encodeBase64(sign.publicKey),
};
} catch (err) {
console.error(err);
return;
}
};
// (UTF8 content, keys object) => Uint8Array block // (UTF8 content, keys object) => Uint8Array block
Block.encrypt = function (version, content, keys) { Block.encrypt = function (version, content, keys) {
var u8 = Nacl.util.decodeUTF8(content); var u8 = Nacl.util.decodeUTF8(content);

Loading…
Cancel
Save