Keys: Fixes and Improvements

- Added file lock using proper-lockfile module to prevent data corruption when multiple shares are queued to write at the same time
- Fixed: sinkShares Table num value throwing error when random number is negative. (Updated 'num' column to Unsigned)
- Changed INT_MIN, INT_MAX to UNSIGNED_INT_MIN, UNSIGNED_INT_MAX
- Added: support for multi-instance in keys module
- Fixed: index_dir and prime_file throwing error on startup
- Added: on init, create index directory if not exist
- Fixed: sink_chest. pick and active_pick returning undefined sometimes
- Fixed: various syntax bugs
This commit is contained in:
sairajzero 2022-11-16 22:08:00 +05:30
parent 506087e856
commit e4603078d2
2 changed files with 62 additions and 32 deletions

View File

@ -317,7 +317,7 @@ CREATE table _backupCache(
); );
CREATE TABLE sinkShares( CREATE TABLE sinkShares(
num INT NOT NULL AUTO_INCREMENT, num INT UNSIGNED NOT NULL AUTO_INCREMENT,
share TEXT, share TEXT,
time_stored TIMESTAMP DEFAULT CURRENT_TIMESTAMP, time_stored TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY(num) PRIMARY KEY(num)

View File

@ -2,23 +2,33 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const lockfile = require('proper-lockfile');
const DB = require("./database"); const DB = require("./database");
var _I = ""; //Instance support
for (let arg of process.argv)
if (/^-I=/.test(arg)) {
_I = arg.split(/=(.*)/s)[1];
break;
}
const { SHARES_PER_NODE, SHARE_THRESHOLD } = require("./_constants")["keys"]; const { SHARES_PER_NODE, SHARE_THRESHOLD } = require("./_constants")["keys"];
const PRIV_EKEY_MIN = 32, const PRIV_EKEY_MIN = 32,
PRIV_EKEY_MAX = 48, PRIV_EKEY_MAX = 48,
PRIME_FILE_TYPE = 'binary', PRIME_FILE_TYPE = 'binary',
INDEX_FILE_TYPE = 'utf-8', INDEX_FILE_TYPE = 'utf-8',
INT_MIN = -2147483648, UNSIGNED_INT_MIN = 0,
INT_MAX = 2147483647, UNSIGNED_INT_MAX = 4294967295,
INDEX_FILE_NAME_LENGTH = 16, INDEX_FILE_NAME_LENGTH = 16,
INDEX_FILE_EXT = '.txt', INDEX_FILE_EXT = '.txt',
MIN_DUMMY_FILES = 16, MIN_DUMMY_FILES = 16,
MAX_DUMMY_FILES = 24, MAX_DUMMY_FILES = 24,
MIN_DUMMY_SIZE_MUL = 0.5, MIN_DUMMY_SIZE_MUL = 0.5,
MAX_DUMMY_SIZE_MUL = 1.5, MAX_DUMMY_SIZE_MUL = 1.5,
SIZE_FACTOR = 100; SIZE_FACTOR = 100,
LOCK_RETRY_MIN_TIME = 1 * 1000,
LOCK_RETRY_MAX_TIME = 2 * 1000;
var node_priv, e_key, node_id, node_pub; //containers for node-key wrapper var node_priv, e_key, node_id, node_pub; //containers for node-key wrapper
const _ = { const _ = {
@ -36,9 +46,13 @@ const _ = {
e_key = floCrypto.randString(n); e_key = floCrypto.randString(n);
node_priv = Crypto.AES.encrypt(key, e_key); node_priv = Crypto.AES.encrypt(key, e_key);
}, },
args_dir: path.resolve(__dirname, '..', '..', 'args'), args_dir: path.resolve(__dirname, '..', 'args'),
index_dir: path.join(this.args_dir, 'indexes'), get index_dir() {
prime_file: path.join(this.args_dir, 'prime_index.b'), return path.join(this.args_dir, `indexes${_I}`)
},
get prime_file() {
return path.join(this.args_dir, `prime_index${_I}.b`)
},
get index_file() { get index_file() {
try { try {
let data = fs.readFileSync(this.prime_file, PRIME_FILE_TYPE), let data = fs.readFileSync(this.prime_file, PRIME_FILE_TYPE),
@ -78,6 +92,14 @@ function initialize() {
} }
} }
} }
try {
if (!fs.existsSync(_.index_dir)) {
fs.mkdirSync(_.index_dir);
}
} catch (error) {
console.debug(error);
return reject("Index directory creation failed");
}
try { //delete all old dummy files try { //delete all old dummy files
let files = fs.readdirSync(_.index_dir); let files = fs.readdirSync(_.index_dir);
for (const file of files) for (const file of files)
@ -115,7 +137,7 @@ function initialize() {
return reject("Update prime file failed"); return reject("Update prime file failed");
} }
if (cur_filename) if (cur_filename)
fs.unlink(path.join(_.index_dir, file), err => err ? console.debug(err) : null); fs.unlink(path.join(_.index_dir, cur_filename + INDEX_FILE_EXT), err => err ? console.debug(err) : null);
resolve("Key management initiated"); resolve("Key management initiated");
}) })
}) })
@ -204,7 +226,7 @@ function getShares(group, id, ignoreDiscarded = true) {
function storeShareAtRandom(share) { function storeShareAtRandom(share) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let rand = floCrypto.randInt(INT_MIN, INT_MAX); let rand = floCrypto.randInt(UNSIGNED_INT_MIN, UNSIGNED_INT_MAX);
DB.query("INSERT INTO sinkShares(num, share) VALUE (?)", [[rand, share]]) DB.query("INSERT INTO sinkShares(num, share) VALUE (?)", [[rand, share]])
.then(result => resolve(result.insertId)).catch(error => { .then(result => resolve(result.insertId)).catch(error => {
if (error.code === "ER_DUP_ENTRY") if (error.code === "ER_DUP_ENTRY")
@ -222,26 +244,33 @@ function addShare(group, id, ref, share) {
checkIfDiscarded(id).then(result => { checkIfDiscarded(id).then(result => {
if (result != false) if (result != false)
return reject("Trying to store share for discarded ID"); return reject("Trying to store share for discarded ID");
readIndexFile().then(data => { lockfile.lock(_.index_file, { retries: { forever: true, minTimeout: LOCK_RETRY_MIN_TIME, maxTimeout: LOCK_RETRY_MAX_TIME } }).then(release => {
if (!(group in data)) const releaseAndReject = err => {
data[group] = {}; release().then(_ => null).catch(error => console.error(error));
if (!(id in data[group])) reject(err);
data[group][id] = [ref];
else if (ref < data[group][id][0])
return reject("reference is lower than current");
else if (ref > data[group][id][0]) {
let old_shares = data[group][id];
data[group][id] = [ref];
old_shares.shift();
DB.query("DELETE FROM sinkShares WHERE num in (?", [old_shares])//delete old shares
.then(_ => null).catch(error => console.error(error));
} }
let encrypted_share = Crypto.AES.encrypt(share, _.node_priv); readIndexFile().then(data => {
console.debug(ref, '|sinkID:', sinkID, '|EnShare:', encrypted_share); if (!(group in data))
storeShareAtRandom(encrypted_share).then(i => { data[group] = {};
data[group][id].push(i); if (!(id in data[group]))
writeIndexFile(data).then(_ => resolve(i)).catch(error => reject(error)); data[group][id] = [ref];
}).catch(error => reject(error)) else if (ref < data[group][id][0])
return reject("reference is lower than current");
else if (ref > data[group][id][0]) {
let old_shares = data[group][id];
data[group][id] = [ref];
old_shares.shift();
DB.query("DELETE FROM sinkShares WHERE num in (?)", [old_shares])//delete old shares
.then(_ => null).catch(error => console.error(error));
}
let encrypted_share = Crypto.AES.encrypt(share, _.node_priv);
console.debug(ref, '|sinkID:', id, '|EnShare:', encrypted_share);
storeShareAtRandom(encrypted_share).then(i => {
data[group][id].push(i);
writeIndexFile(data).then(_ => resolve(i)).catch(error => reject(error))
.finally(_ => release().then(_ => null).catch(error => console.error(error)));
}).catch(error => releaseAndReject(error))
}).catch(error => releaseAndReject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}).catch(error => reject(error)) }).catch(error => reject(error))
}) })
@ -266,7 +295,7 @@ function getStoredList(group = null) {
} else { } else {
let ids = {}; let ids = {};
for (let group in data) for (let group in data)
ids[group] = Object.keys(data.group); ids[group] = Object.keys(data[group]);
resolve(ids); resolve(ids);
} }
}).catch(error => reject(error)) }).catch(error => reject(error))
@ -346,12 +375,13 @@ const sink_ids = {}, sink_chest = {
}, },
pick(group) { pick(group) {
let ids = this.list(group), let ids = this.list(group),
i = floCrypto.randInt(0, ids.length); i = floCrypto.randInt(0, ids.length - 1);
return ids[i]; return ids[i];
}, },
active_pick(group) { active_pick(group) {
console.debug(sink_ids)
let ids = this.active_list(group), let ids = this.active_list(group),
i = floCrypto.randInt(0, ids.length); i = floCrypto.randInt(0, ids.length - 1);
return ids[i]; return ids[i];
}, },
find_group(id) { find_group(id) {
@ -388,7 +418,7 @@ module.exports = {
get node_id() { get node_id() {
return node_id; return node_id;
}, },
get node_id() { get node_pub() {
return node_pub; return node_pub;
}, },
get sink_groups() { get sink_groups() {