/* * @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://t.me/terafoundation */ global.PROCESS_NAME = "TX"; import * as crypto from 'crypto'; import "../core/constant" global.DATA_PATH = global.GetNormalPathString(global.DATA_PATH); global.CODE_PATH = global.GetNormalPathString(global.CODE_PATH); import "../core/library" global.READ_ONLY_DB = 0; require("./child-process"); setInterval(global.PrepareStatEverySecond, 1000); process.on('message', function(msg) { switch (msg.cmd) { case "FindTX": global.TreeFindTX.SaveValue(msg.TX, msg); break; case "SetSmartEvent": global.TreeFindTX.SaveValue("Smart:" + msg.Smart, 1); break; default: break; } }); global.SetStatMode = function(Val) { global.STAT_MODE = Val; return global.STAT_MODE; }; global.HTTP_PORT_NUMBER = 0; import CServerDB from '../core/transaction-validator' import { STreeBuffer } from '../core/base'; import { DB_FORMAT } from '../constant/db-format'; 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.TreeFindTX = new STreeBuffer(30 * 1000, global.CompareItemHashSimple, "string"); setInterval(function() { if (global.SERVER) { global.SERVER.Close(); } DoTXProcess(); }, 10); var BlockTree = new STreeBuffer(30 * 1000, global.CompareItemHashSimple, "number"); global.bShowDetail = 0; var StopTxProcess = 0; var MinimalValidBlock = 0; var LastBlockNum = undefined; function DoTXProcess() { if (StopTxProcess) return; if (LastBlockNum === undefined) InitTXProcess(); var BlockMin = FindMinimal(); if (!BlockMin) { if (global.bShowDetail) global.ToLog("!BlockMin"); return; } var StartTime = Date.now(); if (global.bShowDetail) global.ToLog("BlockMin: " + BlockMin.BlockNum + " LastBlockNum=" + LastBlockNum); var CountTX = 0; for (var Num = BlockMin.BlockNum; Num < BlockMin.BlockNum + 200; Num++) { var EndTime = Date.now(); var Delta = EndTime - StartTime; if (Delta >= 1000) break; var Block = global.SERVER.ReadBlockDB(Num); if (!Block) { if (global.bShowDetail) global.ToLog("!Block"); break; } if (!IsValidSumHash(Block)) { break; } var Item = BlockTree.LoadValue(Block.BlockNum, 1); if (Item && global.CompareArr(Item.SumHash, Block.SumHash) === 0) { if (global.bShowDetail) global.ToLog("WAS CALC: " + Num + " SumHash: " + global.GetHexFromArr(Block.SumHash).substr(0, 12)); continue; } if (Num > 0) { var Block0 = global.SERVER.ReadBlockDB(Num - 1); if (Block0) { var Item0 = BlockTree.LoadValue(Block0.BlockNum, 1); if (Item0 && global.CompareArr(Item0.SumHash, Block0.SumHash) !== 0) { break; } } } global.SERVER.BlockProcessTX(Block); if (Num % 100000 === 0) global.ToLog("CALC: " + Num); CountTX++; if (global.bShowDetail) global.ToLog(" CALC: " + Num + " SumHash: " + global.GetHexFromArr(Block.SumHash).substr(0, 12)); BlockTree.SaveValue(Block.BlockNum, { BlockNum: Block.BlockNum, SumHash: Block.SumHash }); LastBlockNum = Block.BlockNum; } }; function FindMinimal() { var MaxNumBlockDB = global.SERVER.GetMaxNumBlockDB(); if (MaxNumBlockDB && MaxNumBlockDB < LastBlockNum) { if (global.bShowDetail) global.ToLog("MaxNumBlockDB 0) { RewriteAllTransactions(); } Block = global.SERVER.ReadBlockHeaderDB(MinimalValidBlock); return Block; }; function IsValidSumHash(Block) { if (Block.BlockNum <= MinimalValidBlock + global.BLOCK_PROCESSING_LENGTH2) return 1; if (Block.BlockNum < 16) return 1; if (global.IsZeroArr(Block.SumHash)) return 0; var PrevBlock = global.SERVER.ReadBlockHeaderDB(Block.BlockNum - 1); if (!PrevBlock) return 0; var SumHash2 = global.shaarr2(PrevBlock.SumHash, Block.Hash); if (global.CompareArr(SumHash2, Block.SumHash) === 0) return 1; return 0; }; function InitTXProcess() { var StateTX = global.DApps.Accounts.DBStateTX.Read(0); if (!StateTX) { LastBlockNum = 0; var MaxNum = global.DApps.Accounts.DBAccountsHash.GetMaxNum(); if (MaxNum > 0) { var Item = global.DApps.Accounts.DBAccountsHash.Read(MaxNum); if (Item) { LastBlockNum = Item.BlockNum; } } global.ToLog("DETECT NEW VER on BlockNum=" + LastBlockNum, 2); global.DApps.Accounts.DBStateTX.Write({ Num: 0, BlockNum: LastBlockNum, BlockNumMin: MinimalValidBlock }); } StateTX = global.DApps.Accounts.DBStateTX.Read(0); LastBlockNum = StateTX.BlockNum; MinimalValidBlock = StateTX.BlockNumMin; LastBlockNum = global.PERIOD_ACCOUNT_HASH * Math.trunc(LastBlockNum / global.PERIOD_ACCOUNT_HASH); if (LastBlockNum > 100) { LastBlockNum = 1 + LastBlockNum - 100; } global.ToLog("Start CalcMerkleTree", 2); global.DApps.Accounts.CalcMerkleTree(1); global.ToLog("Finsih CalcMerkleTree", 2); if (LastBlockNum <= 0) RewriteAllTransactions(); else global.ToLog("Start NUM = " + LastBlockNum, 2); }; global.ClearDataBase = ClearDataBase; function ClearDataBase() { MinimalValidBlock = 0; for (var key in global.DApps) { global.DApps[key].ClearDataBase(); } LastBlockNum = 0; BlockTree.Clear(); }; global.RewriteAllTransactions = RewriteAllTransactions; function RewriteAllTransactions() { if (MinimalValidBlock > 0) { global.ToLog("*************Cant run RewriteAllTransactions, MinimalValidBlock:" + MinimalValidBlock, 2); return; } global.ToLog("*************RewriteAllTransactions"); for (var key in global.DApps) { global.DApps[key].ClearDataBase(); } LastBlockNum = 0; BlockTree.Clear(); global.ToLog("Start num = " + LastBlockNum, 2); }; global.ReWriteDAppTransactions = ReWriteDAppTransactions; function ReWriteDAppTransactions(Params) { var StartNum = Params.StartNum; var EndNum = Params.EndNum; global.ToLog("ReWriteDAppTransactions: " + StartNum + " - " + EndNum); BlockTree.Clear(); if (StartNum < LastBlockNum) LastBlockNum = StartNum; global.ToLog("Start num = " + LastBlockNum, 2); }; function TXPrepareLoadRest(BlockNum) { StopTxProcess = 1; MinimalValidBlock = BlockNum; global.ToLog("*************TXPrepareLoadRest:" + BlockNum, 2); for (var key in global.DApps) { global.DApps[key].ClearDataBase(); } LastBlockNum = BlockNum; BlockTree.Clear(); global.DApps.Accounts.DBStateTX.Write({ Num: 0, BlockNum: LastBlockNum, BlockNumMin: LastBlockNum }); }; global.TXPrepareLoadRest = TXPrepareLoadRest; function TXWriteAccArr(Params) { var WorkStruct = {}; var WorkFormat = global.DApps.Accounts.FORMAT_ACCOUNT_ROW; global.ToLog("Write accounts: " + Params.StartNum + "-" + Params.Arr.length, 2); for (var i = 0; i < Params.Arr.length; i++) { var Data = global.BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct); Data.Num = Params.StartNum + i; global.DApps.Accounts._DBStateWrite(Data, MinimalValidBlock); } }; global.TXWriteAccArr = TXWriteAccArr; function TXWriteSmartArr(Params) { var WorkStruct = {}; var WorkFormat = DB_FORMAT.FORMAT_SMART_ROW; global.ToLog("Write smarts: " + Params.StartNum + "-" + Params.Arr.length, 2); for (var i = 0; i < Params.Arr.length; i++) { var Data = global.BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct); Data.Num = Params.StartNum + i; global.DApps.Smart.DBSmart.Write(Data); } }; global.TXWriteSmartArr = TXWriteSmartArr; function TXWriteAccHash() { StopTxProcess = 0; global.ToLog("Start TXWriteAccHash: " + MinimalValidBlock, 2); for (var num = 0; true; num++) { var Item = global.DApps.Smart.DBSmart.Read(num); if (!Item) break; var Body = global.BufLib.GetBufferFromObject(Item, DB_FORMAT.FORMAT_SMART_ROW, 20000, {}); global.DApps.Smart.DBSmartWrite(Item); } global.DApps.Accounts.CalcMerkleTree(1); var Block = { BlockNum: MinimalValidBlock, SumHash: [] }; var MaxAccount = global.DApps.Accounts.GetMaxAccount(); var DataHash = global.DApps.Accounts.CalcHash(Block, MaxAccount); return DataHash; }; global.TXWriteAccHash = TXWriteAccHash;