tera/Source/process/tx-process.js

385 lines
11 KiB
JavaScript
Raw Normal View History

2019-02-10 19:53:54 +00:00
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
2019-03-16 16:08:05 +00:00
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
2019-02-10 19:53:54 +00:00
* Web: https://terafoundation.org
* Twitter: https://twitter.com/terafoundation
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
*/
global.PROCESS_NAME = "TX";
const crypto = require('crypto');
const fs = require('fs');
require("../core/constant");
global.DATA_PATH = GetNormalPathString(global.DATA_PATH);
global.CODE_PATH = GetNormalPathString(global.CODE_PATH);
require("../core/library");
global.READ_ONLY_DB = 0;
var LastAlive = Date.now();
setTimeout(function ()
{
setInterval(CheckAlive, 1000);
}, 20000);
setInterval(function ()
{
process.send({cmd:"Alive"});
}, 1000);
setInterval(PrepareStatEverySecond, 1000);
process.send({cmd:"online", message:"OK"});
global.ToLogClient = function (Str,StrKey,bFinal)
{
process.send({cmd:"ToLogClient", Str:"" + Str, StrKey:StrKey, bFinal:bFinal});
};
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 "FindTX":
2019-02-16 17:08:41 +00:00
global.TreeFindTX.SaveValue(msg.TX, msg);
2019-02-10 19:53:54 +00:00
break;
case "SetSmartEvent":
global.TreeFindTX.SaveValue("Smart:" + msg.Smart, 1);
break;
case "Eval":
EvalCode(msg.Code);
break;
default:
break;
}
});
global.SetStatMode = function (Val)
{
global.STAT_MODE = Val;
return global.STAT_MODE;
};
function CheckAlive()
{
if(global.NOALIVE)
return ;
var Delta = Date.now() - LastAlive;
if(Delta > 100 * 1000)
{
2019-04-05 10:13:44 +00:00
ToLog("TX-PROCESS: ALIVE TIMEOUT Stop and exit: " + Delta);
2019-02-10 19:53:54 +00:00
process.exit(0);
return ;
}
};
process.on('uncaughtException', function (err)
{
ToError(err.stack);
ToLog(err.stack);
TO_ERROR_LOG("TX-PROCESS", 777, err);
ToLog("-----------------TX-PROCESS EXIT------------------");
process.exit();
});
process.on('error', function (err)
{
ToError("TX-PROCESS:\n" + err.stack);
ToLog(err.stack);
});
global.HTTP_PORT_NUMBER = 0;
var CServerDB = require("../core/transaction-validator");
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, CompareItemHashSimple, "string");
setInterval(function ()
{
if(SERVER)
SERVER.ClearBufMap();
global.BlockDB.CloseDBFile("block-header");
global.BlockDB.CloseDBFile("block-body");
DoTXProcess();
}, 10);
var BlockTree = new STreeBuffer(30 * 1000, CompareItemHashSimple, "number");
global.bShowDetail = 0;
2019-04-05 10:13:44 +00:00
var MinimalValidBlock = 0;
2019-02-10 19:53:54 +00:00
var LastBlockNum = undefined;
function DoTXProcess()
{
if(LastBlockNum === undefined)
InitTXProcess();
var BlockMin = FindMinimal();
if(!BlockMin)
{
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("!BlockMin");
2019-02-10 19:53:54 +00:00
return ;
}
var StartTime = Date.now();
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("BlockMin: " + BlockMin.BlockNum + " LastBlockNum=" + LastBlockNum);
2019-02-10 19:53:54 +00:00
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 = SERVER.ReadBlockDB(Num);
if(!Block)
{
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("!Block");
2019-02-10 19:53:54 +00:00
break;
}
if(!IsValidSumHash(Block))
{
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("Stop calc: " + Block.BlockNum + " - ZERO");
2019-02-10 19:53:54 +00:00
break;
}
var Item = BlockTree.LoadValue(Block.BlockNum, 1);
if(Item && CompareArr(Item.SumHash, Block.SumHash) === 0)
{
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("WAS CALC: " + Num + " SumHash: " + GetHexFromArr(Block.SumHash).substr(0, 12));
2019-02-10 19:53:54 +00:00
continue;
}
SERVER.BlockProcessTX(Block);
if(Num % 100000 === 0)
ToLog("CALC: " + Num);
CountTX++;
if(bShowDetail)
ToLog(" CALC: " + Num + " SumHash: " + GetHexFromArr(Block.SumHash).substr(0, 12));
BlockTree.SaveValue(Block.BlockNum, {BlockNum:Block.BlockNum, SumHash:Block.SumHash});
LastBlockNum = Block.BlockNum;
}
};
function FindMinimal()
{
var MaxNumBlockDB = SERVER.GetMaxNumBlockDB();
if(MaxNumBlockDB && MaxNumBlockDB < LastBlockNum)
{
LastBlockNum = MaxNumBlockDB - 1;
BlockTree.Clear();
}
2019-04-05 10:13:44 +00:00
if(LastBlockNum < MinimalValidBlock)
LastBlockNum = MinimalValidBlock;
for(var Num = LastBlockNum; Num--; Num >= 0)
2019-02-10 19:53:54 +00:00
{
2019-04-05 10:13:44 +00:00
if(Num < MinimalValidBlock)
break;
2019-02-10 19:53:54 +00:00
var Block = SERVER.ReadBlockHeaderDB(Num);
if(!Block)
{
continue;
}
if(!IsValidSumHash(Block))
{
continue;
}
if(Block.BlockNum % PERIOD_ACCOUNT_HASH === 0)
{
var Item = DApps.Accounts.GetAccountHashItem(Block.BlockNum);
if(Item)
{
BlockTree.SaveValue(Block.BlockNum, Item);
}
}
var Item = BlockTree.LoadValue(Block.BlockNum, 1);
if(Item && CompareArr(Item.SumHash, Block.SumHash) === 0)
return Block;
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("" + Num + " " + Block.BlockNum + ". Item=" + JSON.stringify(Item) + " MinimalValidBlock=" + MinimalValidBlock);
2019-02-10 19:53:54 +00:00
}
2019-04-05 12:33:00 +00:00
if(bShowDetail)
ToLog("MinimalValidBlock:" + MinimalValidBlock);
2019-04-05 10:13:44 +00:00
if(MinimalValidBlock === 0)
RewriteAllTransactions();
Block = SERVER.ReadBlockHeaderDB(MinimalValidBlock);
2019-02-10 19:53:54 +00:00
return Block;
};
function IsValidSumHash(Block)
{
2019-04-05 10:13:44 +00:00
if(Block.BlockNum <= MinimalValidBlock + BLOCK_PROCESSING_LENGTH2)
return 1;
2019-02-10 19:53:54 +00:00
if(Block.BlockNum < 16)
return 1;
if(IsZeroArr(Block.SumHash))
return 0;
var PrevBlock = SERVER.ReadBlockHeaderDB(Block.BlockNum - 1);
if(!PrevBlock)
return 0;
var SumHash2 = shaarr2(PrevBlock.SumHash, Block.Hash);
if(CompareArr(SumHash2, Block.SumHash) === 0)
return 1;
return 0;
};
function InitTXProcess()
{
var StateTX = DApps.Accounts.DBStateTX.Read(0);
if(!StateTX)
{
LastBlockNum = 0;
var MaxNum = DApps.Accounts.DBAccountsHash.GetMaxNum();
if(MaxNum > 0)
{
var Item = DApps.Accounts.DBAccountsHash.Read(MaxNum);
if(Item)
{
LastBlockNum = Item.BlockNum;
}
}
2019-04-05 10:13:44 +00:00
ToLog("DETECT NEW VER on BlockNum=" + LastBlockNum, 2);
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum, BlockNumMin:MinimalValidBlock});
2019-02-10 19:53:54 +00:00
}
StateTX = DApps.Accounts.DBStateTX.Read(0);
LastBlockNum = StateTX.BlockNum;
2019-04-05 10:13:44 +00:00
MinimalValidBlock = StateTX.BlockNumMin;
2019-02-10 19:53:54 +00:00
LastBlockNum = PERIOD_ACCOUNT_HASH * Math.trunc(LastBlockNum / PERIOD_ACCOUNT_HASH);
if(LastBlockNum > 100)
{
LastBlockNum = 1 + LastBlockNum - 100;
}
if(LastBlockNum <= 0)
RewriteAllTransactions();
else
2019-04-05 10:13:44 +00:00
ToLog("Start NUM = " + LastBlockNum, 2);
2019-02-10 19:53:54 +00:00
DApps.Accounts.CalcMerkleTree();
};
2019-04-05 10:13:44 +00:00
global.ClearDataBase = ClearDataBase;
function ClearDataBase()
{
MinimalValidBlock = 0;
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
LastBlockNum = 0;
BlockTree.Clear();
};
global.RewriteAllTransactions = RewriteAllTransactions;
2019-02-10 19:53:54 +00:00
function RewriteAllTransactions()
{
2019-04-05 10:13:44 +00:00
if(MinimalValidBlock > 0)
{
ToLog("*************Cant run RewriteAllTransactions, MinimalValidBlock:" + MinimalValidBlock, 2);
return ;
}
2019-02-10 19:53:54 +00:00
ToLog("*************RewriteAllTransactions");
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
LastBlockNum = 0;
BlockTree.Clear();
2019-04-05 10:13:44 +00:00
ToLog("Start num = " + LastBlockNum, 2);
2019-02-10 19:53:54 +00:00
};
2019-04-05 10:13:44 +00:00
global.ReWriteDAppTransactions = ReWriteDAppTransactions;
2019-02-10 19:53:54 +00:00
2019-04-05 10:13:44 +00:00
function ReWriteDAppTransactions(Params)
2019-02-10 19:53:54 +00:00
{
2019-04-05 10:13:44 +00:00
var StartNum = Params.StartNum;
var EndNum = Params.EndNum;
2019-02-10 19:53:54 +00:00
ToLog("ReWriteDAppTransactions: " + StartNum + " - " + EndNum);
BlockTree.Clear();
if(StartNum < LastBlockNum)
LastBlockNum = StartNum;
2019-04-05 10:13:44 +00:00
ToLog("Start num = " + LastBlockNum, 2);
};
function TXPrepareLoadRest(BlockNum)
{
MinimalValidBlock = BlockNum;
ToLog("*************TXPrepareLoadRest:" + BlockNum, 2);
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
LastBlockNum = BlockNum;
BlockTree.Clear();
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum, BlockNumMin:LastBlockNum});
};
global.TXPrepareLoadRest = TXPrepareLoadRest;
function TXWriteAccArr(Params)
{
var WorkStruct = {};
var WorkFormat = DApps.Accounts.FORMAT_ACCOUNT_ROW;
ToLog("Write accounts: " + Params.StartNum + "-" + Params.Arr.length, 2);
for(var i = 0; i < Params.Arr.length; i++)
{
var Data = BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct);
Data.Num = Params.StartNum + i;
DApps.Accounts._DBStateWrite(Data, MinimalValidBlock);
}
};
global.TXWriteAccArr = TXWriteAccArr;
function TXWriteSmartArr(Params)
{
var WorkStruct = {};
var WorkFormat = DApps.Smart.FORMAT_ROW;
ToLog("Write smarts: " + Params.StartNum + "-" + Params.Arr.length, 2);
for(var i = 0; i < Params.Arr.length; i++)
{
var Data = BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct);
Data.Num = Params.StartNum + i;
DApps.Smart.DBSmart.Write(Data);
}
};
global.TXWriteSmartArr = TXWriteSmartArr;
function TXWriteAccHash()
{
ToLog("Start TXWriteAccHash", 2);
for(var num = 0; true; num++)
{
var Item = DApps.Smart.DBSmart.Read(num);
if(!Item)
break;
var Body = BufLib.GetBufferFromObject(Item, DApps.Smart.FORMAT_ROW, 20000, {});
DApps.Smart.DBSmartWrite(Item);
}
var Block = {BlockNum:MinimalValidBlock, SumHash:[]};
var MaxAccount = DApps.Accounts.GetMaxAccount();
var DataHash = DApps.Accounts.CalcHash(Block, MaxAccount);
return DataHash;
2019-02-10 19:53:54 +00:00
};
2019-04-05 10:13:44 +00:00
global.TXWriteAccHash = TXWriteAccHash;
2019-02-10 19:53:54 +00:00
global.EvalCode = function (Code)
{
var Result;
try
{
var ret = eval(Code);
Result = JSON.stringify(ret, "", 4);
}
catch(e)
{
Result = "" + e;
}
return Result;
};