UNPKG

orwelldb

Version:

Library, wich helps syncronize blockchain and any database use datascript protocol to write operations (can be wroten in blockchain transactions hex like scriptSig or scriptPubKey)

297 lines (232 loc) 10.3 kB
const bitPony = require('bitpony'); const owl = require('bitowl'); encodeUtf8 = function (str) { return unescape(encodeURIComponent(str)); }; decodeUtf8 = function (str) { return decodeURIComponent(escape(str)); }; bitPony.extend('json', function () { var VERSION = 0xf0f001f, FUNC = 0xf5, OBJ = 0xf4, STR = 0xf1, NUMBER = 0xf2, FLOAT = 0xf6, ARR = 0xf3, NULL = 0xf0, BOOL = 0xf7; //first byte - type: //0xf4 - json object //0xf1 - string next //0xf2 - var_int (integer) //0xf3 - Array //0xf0 - NULL //0xf5 - js function callback //sort by keysname asc //format typebyte-(string)-key-val return { read: function (buffer) { if (typeof buffer == 'string') buffer = new Buffer(buffer, 'hex') if (buffer.length == 0 || !buffer) buffer = new Buffer([NULL, 0]); var stream = new bitPony.reader(buffer); var unserializePrimitive = function (stream, offset) { var item = {}; var res = stream.uint8(offset); item.type = res.result; offset = res.offset; res = stream.string(offset); item.key = decodeUtf8(res.result.toString()); offset = res.offset; if (item.type == NUMBER || item.type == BOOL) res = stream.var_int(offset); else//str res = stream.string(offset); if (item.type == NULL) item.value = null; else if (item.type == BOOL) item.value = !!res.result; else if (item.type == NUMBER) item.value = res.result; else if (item.type == FLOAT) item.value = parseFloat(res.result); else if (item.type == FUNC) { item.value = new Function("return " + decodeUtf8(res.result.toString()))() } else { item.value = decodeUtf8(res.result.toString()); } offset = res.offset; return { offset: offset, item: item }; } var unserializeArray = function (stream, offset) { var item = {value: [], count: 0}; var res = stream.uint8(offset);//array flag item.type = res.result; offset = res.offset; res = stream.string(offset); item.key = decodeUtf8((res.result.toString())); offset = res.offset; res = stream.var_int(offset); item.count = res.result; offset = res.offset; for (var i = 0; i < item.count; i++) { var type = stream.uint8(offset); offset = type.offset; if (type.result == OBJ) { res = unserializeObject(stream, offset - 1); } else if (type.result == ARR) { res = unserializeArray(stream, offset - 1); } else { res = unserializePrimitive(stream, offset - 1); } offset = res.offset; item.value.push(res.item.value);//keys is null } return { offset: offset, item: item }; } var unserializeObject = function (stream, offset) { var item = {value: {}, count: 0}; var res = stream.uint8(offset); item.type = res.result; offset = res.offset; res = stream.string(offset); item.key = decodeUtf8(res.result.toString()); offset = res.offset; res = stream.var_int(offset); item.count = res.result; offset = res.offset; for (var i = 0; i < item.count; i++) { var type = stream.uint8(offset); offset = type.offset; if (type.result == OBJ) { res = unserializeObject(stream, offset - 1); } else if (type.result == ARR) { res = unserializeArray(stream, offset - 1); } else { res = unserializePrimitive(stream, offset - 1); } offset = res.offset; item.value[res.item.key] = res.item.value; } return { offset: offset, item: item }; } var version, sign; var res = stream.uint32(0); version = res.result; res = stream.uint32(res.offset) sign = res.result; var mysign = parseInt(bitPony.tool.sha256(bitPony.tool.sha256(buffer.slice(res.offset, buffer.length))).slice(0, 4).toString('hex'), 16); //another version its ok //if (version != VERSION) //throw new Error('binay json package is not valid version recived'); if (mysign != sign) throw new Error('binay json package is not valid'); res = unserializeObject(stream, res.offset).item.value; return res; }, write: function (obj) { var b = new Buffer(""); var stream = new bitPony.writer(b); var serializePrimitive = function (stream, type, key, val) { stream.uint8(type, true); stream.string(new Buffer(encodeUtf8(key)), true) if (type == NULL) { stream.var_int(0, true); } else if (type == NUMBER || type == BOOL) stream.var_int(val, true); else { if (val.toString() != "") { stream.string(new Buffer(encodeUtf8(val.toString() || "")), true) } else { stream.uint8(0, true) } } } var serializeArray = function (stream, key, arr, sort) { stream.uint8(ARR, true); stream.string(new Buffer(encodeUtf8(key)), true); stream.var_int(arr.length, true); if (sort) arr.sort(function (a, b) { return a > b; }); for (var i in arr) { var t = STR; if (arr[i] instanceof Function) { t = FUNC; } else if (arr[i] instanceof Array) { serializeArray(stream, "", arr[i], sort); continue; } else if (arr[i] instanceof Object) { serializeObject(stream, "", arr[i], sort); continue; } else if (arr[i] == null) { t = NULL; arr[i] = 0; } else if (arr[i] === true) { t = BOOL; arr[i] = 1; } else if (arr[i] === false) { t = BOOL; arr[i] = 0; } else if (arr[i] !== "" && /^\d+$/.test(arr[i]) && isFinite(arr[i])) t = NUMBER; serializePrimitive(stream, t, "", arr[i]); } } var serializeObject = function (stream, key, obj, sort) { if (obj == null || typeof obj == 'undefined') obj = {}; var keys = Object.keys(obj); stream.uint8(OBJ, true); stream.string(new Buffer(encodeUtf8("" + key)), true); stream.var_int(keys.length, true); if (sort) keys.sort(function (a, b) { return a > b; }); for (var i in keys) { var o = obj[keys[i]]; var t = STR;//functions and others if (o instanceof Function) { t = FUNC; } else if (o instanceof Array) { t = ARR; serializeArray(stream, keys[i], o, sort); continue; } else if (o instanceof Object) { t = OBJ; serializeObject(stream, keys[i], o, sort); continue; } else if (o == null) { t = NULL; o = 0; } else if (o === true) { o = 1; t = BOOL; } else if (o === false) { o = 0; t = BOOL; } else if (o !== "" && /^\d+$/.test(o) && isFinite(o) && (typeof o != 'string')) { t = NUMBER; } //for numbers and string serializePrimitive(stream, t, keys[i], o); } } serializeObject(stream, "", obj); var buff = stream.getBuffer(); var sign = bitPony.tool.sha256(bitPony.tool.sha256(buff)) var stream2 = new bitPony.writer(new Buffer("")); stream2.uint32(VERSION, true)//version stream2.uint32(parseInt(sign.slice(0, 4).toString('hex'), 16), true);//digest return Buffer.concat([ stream2.getBuffer(), buff ]) } } });