/* * @project: TERA * @version: Development (beta) * @license: MIT (not for evil) * @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com] * Web: https://terafoundation.org * Twitter: https://twitter.com/terafoundation * Telegram: https://web.telegram.org/#/im?p=@terafoundation */ global.PROCESS_NAME = "STATIC"; const crypto = require('crypto'); const fs = require('fs'); require("../core/constant"); require('../core/block-loader-const'); require('../core/rest_tables.js'); require('../dapp/accounts.js'); require('../dapp/smart.js'); global.DATA_PATH = GetNormalPathString(global.DATA_PATH); global.CODE_PATH = GetNormalPathString(global.CODE_PATH); require("../core/library"); global.READ_ONLY_DB = 1; var LastAlive = Date.now(); setTimeout(function () { setInterval(CheckAlive, 1000); }, 20000); setInterval(function () { process.send({cmd:"Alive"}); }, 1000); process.send({cmd:"online", message:"OK"}); process.on('message', function (msg) { LastAlive = Date.now(); switch(msg.cmd) { case "ALive": break; case "Exit": process.exit(0); break; case "call": var Err = 0; var Ret; try { Ret = global[msg.Name](msg.Params); } catch(e) { Err = 1; Ret = "" + e; } if(msg.id) process.send({cmd:"retcall", id:msg.id, Err:Err, Params:Ret}); break; case "GETBLOCKHEADER": GETBLOCKHEADER(msg); break; case "GETBLOCK": GETBLOCK(msg); break; case "GETCODE": GETCODE(msg); break; case "GETREST": GETREST(msg); break; case "GETSMART": GETSMART(msg); break; } }); function CheckAlive() { if(global.NOALIVE) return ; var Delta = Date.now() - LastAlive; if(Delta > CHECK_STOP_CHILD_PROCESS) { ToLog("STATIC-DB: ALIVE TIMEOUT Stop and exit: " + Delta + "/" + global.CHECK_STOP_CHILD_PROCESS); process.exit(0); return ; } }; process.on('uncaughtException', function (err) { ToError(err.stack); ToLog(err.stack); TO_ERROR_LOG("STATIC-DB", 777, err); ToLog("-----------------STATIC-DB EXIT------------------"); process.exit(); }); process.on('error', function (err) { ToError("STATIC-DB:\n" + err.stack); ToLog(err.stack); }); var CServerDB = require("../core/db/block-db"); var KeyPair = crypto.createECDH('secp256k1'); KeyPair.setPrivateKey(Buffer.from([77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77])); global.SERVER = new CServerDB(KeyPair, undefined, undefined, false, true); global.HTTP_PORT_NUMBER = 0; setInterval(function () { if(SERVER) SERVER.ClearBufMap(); DApps.Accounts.Close(); DApps.Smart.DBSmart.Close(); global.BlockDB.CloseDBFile("block-header"); global.BlockDB.CloseDBFile("block-body"); }, 1000); function GETBLOCKHEADER(msg) { var Data = msg.Data; var StartNum = undefined; var BlockNum; var LoadHash = Data.Hash; var Foward = Data.Foward; if(Foward) { var BlockDB = SERVER.ReadBlockHeaderDB(Data.BlockNum); if(BlockDB && BlockDB.SumHash && (CompareArr(BlockDB.SumHash, LoadHash) === 0 || IsZeroArr(LoadHash))) { StartNum = Data.BlockNum - BLOCK_PROCESSING_LENGTH2; if(StartNum < 0) StartNum = 0; BlockNum = StartNum + COUNT_BLOCKS_FOR_LOAD + BLOCK_PROCESSING_LENGTH2; if(BlockNum > SERVER.GetMaxNumBlockDB()) BlockNum = SERVER.GetMaxNumBlockDB(); } } else { BlockNum = Data.BlockNum; var IsSum = Data.IsSum; var Count = Data.Count; if(!Count || Count < 0 || BlockNum < 0) return ; if(Count > COUNT_BLOCKS_FOR_LOAD) Count = COUNT_BLOCKS_FOR_LOAD; Count += BLOCK_PROCESSING_LENGTH2; var BlockDB = SERVER.ReadBlockHeaderDB(BlockNum); if(BlockDB && (BlockDB.Prepared && (!IsSum) && BlockDB.Hash && CompareArr(BlockDB.Hash, LoadHash) === 0 || BlockDB.bSave && IsSum && BlockDB.SumHash && CompareArr(BlockDB.SumHash, LoadHash) === 0)) { StartNum = BlockNum - Count + 1; if(StartNum < 0) StartNum = 0; } } var BufWrite = SERVER.BlockChainToBuf(StartNum, StartNum, BlockNum); process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETBLOCKHEADER", Context:msg.Context, Data:BufWrite}); }; function GETBLOCK(msg) { var Data = msg.Data; var BlockNum = Data.BlockNum; var TreeHash = Data.TreeHash; if(msg.Context.SendCount) { return ; } var BufWrite; var BlockDB = SERVER.ReadBlockDB(BlockNum); var StrSend; if(BlockDB && (CompareArr(BlockDB.TreeHash, TreeHash) === 0 || IsZeroArr(TreeHash))) { var BufWrite = BufLib.GetBufferFromObject(BlockDB, FORMAT_BLOCK_TRANSFER, MAX_PACKET_LENGTH, WRK_BLOCK_TRANSFER); StrSend = "OK"; var TreeHashTest = CalcTreeHashFromArrBody(BlockDB.BlockNum, BlockDB.arrContent); if(CompareArr(BlockDB.TreeHash, TreeHashTest) !== 0) { ToLog("1. BAD CMP TreeHash block=" + BlockNum + " TO: " + msg.addrStr.substr(0, 8) + " TreeHashTest=" + GetHexFromArr(TreeHashTest) + " DB TreeHash=" + GetHexFromArr(BlockDB.TreeHash)); StrSend = "NO"; } } if(StrSend === "OK") { ADD_TO_STAT("BLOCK_SEND"); } else { BufWrite = BufLib.GetNewBuffer(100); StrSend = "NO"; } process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETGETBLOCK", Context:msg.Context, Data:BufWrite}); }; function GETCODE(msg) { var VersionNum = msg.Data; var fname = GetDataPath("Update/wallet-" + VersionNum + ".zip"); if(fs.existsSync(fname)) { var data = fs.readFileSync(fname); process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETCODE", Context:msg.Context, Data:data}); } }; function GETREST(msg) { var Data = msg.Data; if(!Data.BlockNum) return ; var BlockNumRest = Data.BlockNum; var arr = GetCurrentRestArr(); var BufLength; var nResult = 0; for(var i = 0; i < arr.length; i++) { if(arr[i] === BlockNumRest) { nResult = 1; break; } } var ArrRest = []; if(nResult) { var WorkStruct = {}; var WorkFormat = DApps.Accounts.FORMAT_ACCOUNT_ROW; var WorkFormatLength = DApps.Accounts.SIZE_ACCOUNT_ROW; var Max = DApps.Accounts.DBState.GetMaxNum(); var LengthAccount = Data.Count; if(LengthAccount > MAX_ACCOUNTS_TRANSFER) LengthAccount = MAX_ACCOUNTS_TRANSFER; var EndAccount = Data.AccNum + LengthAccount - 1; if(EndAccount > Max) EndAccount = Max; var FindItem; for(var Num = Data.AccNum; Num <= EndAccount; Num++) { FindItem = undefined; var RestData = DApps.Accounts.ReadRest(Num); var Data = DApps.Accounts.DBState.Read(Num); if(!Data) break; var CountZero = 0; for(var i = RestData.Arr.length - 1; i >= 0; i--) { var Item = RestData.Arr[i]; if(!Item.BlockNum) { CountZero++; continue; } if(Item.BlockNum <= BlockNumRest) { if(!FindItem || Item.BlockNum > FindItem.BlockNum) { FindItem = Item; } } } if(FindItem) { Data.Value = FindItem.Value; } else { if(CountZero !== RestData.Arr.length) continue; } var Buf = BufLib.GetBufferFromObject(Data, WorkFormat, WorkFormatLength, WorkStruct); ArrRest.push(Buf); } BufLength = 1000 + ArrRest.length * WorkFormatLength; } else { BufLength = 1000; } var Data2 = {Result:nResult, BlockNum:BlockNumRest, Arr:ArrRest}; var BufWrite = BufLib.GetBufferFromObject(Data2, FORMAT_REST_TRANSFER, BufLength, {}); process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETREST", Context:msg.Context, Data:BufWrite}); }; function GETSMART(msg) { var Data = msg.Data; if(!Data.Count) return ; var BufLength = 1000; var SizeForSend = 200 * 1024; var Arr = []; for(var Num = Data.SmartNum; Num < Data.SmartNum + Data.Count; Num++) { var BufSmart = DApps.Smart.DBSmart.Read(Num, 1); if(!BufSmart) break; SizeForSend = SizeForSend - BufSmart.length; if(SizeForSend < 0) break; BufLength += BufSmart.length; Arr.push(BufSmart); } var Data2 = {Result:Arr.length ? 1 : 0, Arr:Arr}; var BufWrite = BufLib.GetBufferFromObject(Data2, FORMAT_SMART_TRANSFER, BufLength, {}); process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETSMART", Context:msg.Context, Data:BufWrite}); };