2019-07-10 04:01:15 +00:00
|
|
|
/*
|
|
|
|
* @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 = "STATIC";
|
|
|
|
import * as crypto from 'crypto';
|
2019-07-10 07:59:04 +00:00
|
|
|
import * as fs from 'fs'
|
|
|
|
import "../core/constant"
|
|
|
|
import '../core/block-loader-const'
|
|
|
|
import '../core/rest_tables'
|
|
|
|
import '../system/accounts'
|
|
|
|
import '../system/smart'
|
|
|
|
global.DATA_PATH = global.GetNormalPathString(global.DATA_PATH);
|
|
|
|
global.CODE_PATH = global.GetNormalPathString(global.CODE_PATH);
|
|
|
|
import "../core/library"
|
2019-07-18 11:22:32 +00:00
|
|
|
import "./child-process"
|
2019-07-10 04:01:15 +00:00
|
|
|
global.READ_ONLY_DB = 1;
|
2019-07-18 11:22:32 +00:00
|
|
|
|
2019-07-10 04:01:15 +00:00
|
|
|
process.on('message', function(msg) {
|
|
|
|
switch (msg.cmd) {
|
|
|
|
case "GETBLOCKHEADER":
|
|
|
|
GETBLOCKHEADER(msg);
|
|
|
|
break;
|
|
|
|
case "GETBLOCKHEADER100":
|
|
|
|
GETBLOCKHEADER100(msg);
|
|
|
|
break;
|
|
|
|
case "GETBLOCK":
|
|
|
|
GETBLOCK(msg);
|
|
|
|
break;
|
|
|
|
case "GETCODE":
|
|
|
|
GETCODE(msg);
|
|
|
|
break;
|
|
|
|
case "GETREST":
|
|
|
|
GETREST(msg);
|
|
|
|
break;
|
|
|
|
case "GETSMART":
|
|
|
|
GETSMART(msg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-07-11 05:35:16 +00:00
|
|
|
import CServerDB from '../core/db/block-db'
|
2019-07-13 10:48:51 +00:00
|
|
|
import { DB_FORMAT } from '../constant/db-format';
|
2019-07-10 04:01:15 +00:00
|
|
|
var KeyPair = crypto.createECDH('secp256k1');
|
2019-07-10 09:28:08 +00:00
|
|
|
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]));
|
2019-07-10 04:01:15 +00:00
|
|
|
global.SERVER = new CServerDB(KeyPair, undefined, undefined, false, true);
|
|
|
|
global.HTTP_PORT_NUMBER = 0;
|
|
|
|
setInterval(function() {
|
2019-07-10 07:59:04 +00:00
|
|
|
if (global.SERVER)
|
2019-07-10 04:01:15 +00:00
|
|
|
global.SERVER.Close();
|
|
|
|
global.DApps.Accounts.Close();
|
|
|
|
global.DApps.Smart.DBSmart.Close();
|
|
|
|
}, 1000);
|
|
|
|
|
|
|
|
function GETBLOCKHEADER100(msg) {
|
|
|
|
return;
|
|
|
|
var Data = msg.Data;
|
|
|
|
var BlockNum = Data.BlockNum;
|
|
|
|
if (BlockNum % 100 !== 0)
|
|
|
|
return;
|
|
|
|
var EndNum100 = BlockNum / 100;
|
|
|
|
var LoadHash100 = Data.Hash;
|
2019-07-11 07:52:17 +00:00
|
|
|
var Hash100;
|
2019-07-10 04:01:15 +00:00
|
|
|
var Count = Data.Count;
|
|
|
|
if (!Count || Count < 0 || !EndNum100)
|
|
|
|
return;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (Count > global.COUNT_BLOCKS_FOR_LOAD)
|
|
|
|
Count = global.COUNT_BLOCKS_FOR_LOAD;
|
2019-07-10 04:01:15 +00:00
|
|
|
var Arr = [];
|
|
|
|
var Data100 = global.SERVER.DBHeader100.Read(EndNum100);
|
|
|
|
if (Data100 && global.CompareArr(Data100.Hash100, LoadHash100) === 0) {
|
|
|
|
var StartNum = EndNum100 - Count + 1;
|
|
|
|
if (StartNum < 0)
|
|
|
|
StartNum = 0;
|
|
|
|
for (var Num = StartNum; Num <= EndNum100; Num++) {
|
|
|
|
Data100 = global.SERVER.DBHeader100.Read(Num);
|
|
|
|
if (Num === StartNum)
|
|
|
|
Arr.push(Data100.Hash100);
|
|
|
|
Arr.push(Data100.Hash);
|
|
|
|
}
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
var BufWrite = global.BufLib.GetBufferFromObject(Arr, "[hash]", global.MAX_PACKET_LENGTH, {});
|
2019-07-10 04:01:15 +00:00
|
|
|
global.ToLog("GETBLOCKHEADER100 Send Arr=" + Arr.length + " - " + BlockNum);
|
|
|
|
process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETBLOCKHEADER100", Context: msg.Context, Data: BufWrite });
|
|
|
|
};
|
|
|
|
|
|
|
|
function GETBLOCKHEADER(msg) {
|
|
|
|
var Data = msg.Data;
|
|
|
|
var StartNum = undefined;
|
|
|
|
var BlockNum;
|
|
|
|
var LoadHash = Data.Hash;
|
|
|
|
var Foward = Data.Foward;
|
|
|
|
if (Foward) {
|
|
|
|
var BlockDB = global.SERVER.ReadBlockHeaderDB(Data.BlockNum);
|
2019-07-10 07:59:04 +00:00
|
|
|
if (BlockDB && BlockDB.SumHash && (global.CompareArr(BlockDB.SumHash, LoadHash) === 0 || global.IsZeroArr(LoadHash))) {
|
2019-07-10 04:01:15 +00:00
|
|
|
StartNum = Data.BlockNum - global.BLOCK_PROCESSING_LENGTH2;
|
|
|
|
if (StartNum < 0)
|
|
|
|
StartNum = 0;
|
2019-07-10 07:59:04 +00:00
|
|
|
BlockNum = StartNum + global.COUNT_BLOCKS_FOR_LOAD + global.BLOCK_PROCESSING_LENGTH2;
|
2019-07-10 04:01:15 +00:00
|
|
|
if (BlockNum > global.SERVER.GetMaxNumBlockDB())
|
|
|
|
BlockNum = global.SERVER.GetMaxNumBlockDB();
|
|
|
|
}
|
2019-07-11 07:52:17 +00:00
|
|
|
} else {
|
2019-07-10 04:01:15 +00:00
|
|
|
BlockNum = Data.BlockNum;
|
|
|
|
var IsSum = Data.IsSum;
|
|
|
|
var Count = Data.Count;
|
|
|
|
if (!Count || Count < 0 || BlockNum < 0)
|
|
|
|
return;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (Count > global.COUNT_BLOCKS_FOR_LOAD)
|
|
|
|
Count = global.COUNT_BLOCKS_FOR_LOAD;
|
2019-07-10 04:01:15 +00:00
|
|
|
Count += global.BLOCK_PROCESSING_LENGTH2;
|
|
|
|
var BlockDB = global.SERVER.ReadBlockHeaderDB(BlockNum);
|
|
|
|
if (BlockDB && (BlockDB.Prepared && (!IsSum) && BlockDB.Hash && global.CompareArr(BlockDB.Hash, LoadHash) === 0 || BlockDB.bSave && IsSum && BlockDB.SumHash && global.CompareArr(BlockDB.SumHash,
|
|
|
|
LoadHash) === 0)) {
|
|
|
|
StartNum = BlockNum - Count + 1;
|
|
|
|
if (StartNum < 0)
|
|
|
|
StartNum = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var BufWrite = global.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 = global.SERVER.ReadBlockDB(BlockNum);
|
|
|
|
var StrSend;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (BlockDB && (global.CompareArr(BlockDB.TreeHash, TreeHash) === 0 || global.IsZeroArr(TreeHash))) {
|
2019-07-13 10:48:51 +00:00
|
|
|
var BufWrite = global.BufLib.GetBufferFromObject(BlockDB, DB_FORMAT.FORMAT_BLOCK_TRANSFER, global.MAX_PACKET_LENGTH, global.WRK_BLOCK_TRANSFER);
|
2019-07-10 04:01:15 +00:00
|
|
|
StrSend = "OK";
|
|
|
|
}
|
|
|
|
if (StrSend === "OK") {
|
|
|
|
global.ADD_TO_STAT("BLOCK_SEND");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
BufWrite = global.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 = global.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;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (global.IsZeroArr(Data.AccHash)) {
|
2019-07-10 04:01:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
var BlockNumRest = Data.BlockNum;
|
|
|
|
var RestIndexArr = GetCurrentRestArr();
|
|
|
|
var nResult = 0;
|
|
|
|
for (var i = 0; i < RestIndexArr.length; i++) {
|
|
|
|
if (RestIndexArr[i] === BlockNumRest) {
|
|
|
|
nResult = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var BufLength = 1000;
|
|
|
|
var ProofHash = [];
|
|
|
|
var ProofArrL = [];
|
|
|
|
var ProofArrR = [];
|
|
|
|
var ArrRest = [];
|
|
|
|
if (nResult) {
|
2019-07-11 07:52:17 +00:00
|
|
|
var WorkStruct = {};
|
|
|
|
var WorkFormat = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
|
2019-07-10 04:01:15 +00:00
|
|
|
var WorkFormatLength = global.DApps.Accounts.SIZE_ACCOUNT_ROW;
|
|
|
|
var Max = global.DApps.Accounts.DBState.GetMaxNum();
|
|
|
|
var LengthAccount = Data.Count;
|
2019-07-10 07:59:04 +00:00
|
|
|
if (LengthAccount > global.MAX_ACCOUNTS_TRANSFER)
|
|
|
|
LengthAccount = global.MAX_ACCOUNTS_TRANSFER;
|
2019-07-10 04:01:15 +00:00
|
|
|
var StartAccount = Data.AccNum;
|
|
|
|
var EndAccount = StartAccount + LengthAccount - 1;
|
|
|
|
if (EndAccount > Max)
|
|
|
|
EndAccount = Max;
|
|
|
|
var Tree = GetRestMerkleTree(BlockNumRest, RestIndexArr);
|
|
|
|
if (global.CompareArr(Data.AccHash, Tree.Root) !== 0) {
|
|
|
|
global.ToLog("Get bad rest acc hash: " + BlockNumRest + " = " + global.GetHexFromArr(Data.AccHash) + "/" + global.GetHexFromArr(Tree.Root), 2);
|
|
|
|
ArrRest = [];
|
|
|
|
nResult = 0;
|
2019-07-13 06:10:12 +00:00
|
|
|
} else {
|
2019-07-10 04:01:15 +00:00
|
|
|
ArrRest = GetArrRest(BlockNumRest, StartAccount, EndAccount);
|
|
|
|
ProofHash = Tree.Root;
|
2019-07-10 07:59:04 +00:00
|
|
|
var RetProof = global.GetMerkleProof(Tree.LevelsHash, StartAccount, EndAccount);
|
2019-07-10 04:01:15 +00:00
|
|
|
ProofArrL = RetProof.ArrL;
|
|
|
|
ProofArrR = RetProof.ArrR;
|
|
|
|
BufLength = 1000 + ArrRest.length * WorkFormatLength;
|
|
|
|
BufLength += ProofArrL.length * 32 + ProofArrR.length * 32 + 32;
|
|
|
|
}
|
|
|
|
}
|
2019-07-13 06:10:12 +00:00
|
|
|
var Data2 = {
|
|
|
|
Result: nResult,
|
|
|
|
Arr: ArrRest,
|
|
|
|
Version: 1,
|
|
|
|
ProofHash: ProofHash,
|
|
|
|
ProofArrL: ProofArrL,
|
|
|
|
ProofArrR: ProofArrR
|
|
|
|
};
|
2019-07-13 10:48:51 +00:00
|
|
|
var BufWrite = global.BufLib.GetBufferFromObject(Data2, DB_FORMAT.FORMAT_REST_TRANSFER, BufLength, {});
|
2019-07-13 06:10:12 +00:00
|
|
|
process.send({
|
|
|
|
cmd: "Send",
|
|
|
|
addrStr: msg.addrStr,
|
|
|
|
Method: "RETREST",
|
|
|
|
Context: msg.Context,
|
|
|
|
Data: BufWrite
|
|
|
|
});
|
2019-07-10 04:01:15 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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 = global.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 };
|
2019-07-13 10:48:51 +00:00
|
|
|
var BufWrite = global.BufLib.GetBufferFromObject(Data2, DB_FORMAT.FORMAT_SMART_TRANSFER, BufLength, {});
|
2019-07-13 06:10:12 +00:00
|
|
|
process.send({
|
|
|
|
cmd: "Send",
|
|
|
|
addrStr: msg.addrStr,
|
|
|
|
Method: "RETSMART",
|
|
|
|
Context: msg.Context,
|
|
|
|
Data: BufWrite
|
|
|
|
});
|
2019-07-10 04:01:15 +00:00
|
|
|
};
|
|
|
|
var glMapForHash = {};
|
|
|
|
|
2019-07-10 07:59:04 +00:00
|
|
|
function GetArrRest(BlockNumRest, StartAccount, EndAccount, bHashOnly?) {
|
2019-07-10 04:01:15 +00:00
|
|
|
var ArrRest = [];
|
|
|
|
var WorkStruct = {};
|
|
|
|
var WorkFormat = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
|
|
|
|
var WorkFormatLength = global.DApps.Accounts.SIZE_ACCOUNT_ROW;
|
|
|
|
for (var Num = StartAccount; Num <= EndAccount; Num++) {
|
|
|
|
var FindItem = undefined;
|
|
|
|
var RestData = global.DApps.Accounts.ReadRest(Num);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
var BlocNumMap = 0;
|
|
|
|
var StateDataValue = undefined;
|
|
|
|
if (FindItem) {
|
|
|
|
StateDataValue = FindItem.Value;
|
|
|
|
BlocNumMap = Item.BlockNum;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (CountZero !== RestData.Arr.length)
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
var StateData = global.DApps.Accounts.DBState.Read(Num);
|
|
|
|
if (!StateData)
|
|
|
|
break;
|
|
|
|
if (StateDataValue)
|
|
|
|
StateData.Value = StateDataValue;
|
|
|
|
if (bHashOnly) {
|
|
|
|
var key = "" + Num + "-" + BlocNumMap;
|
|
|
|
var Hash = glMapForHash[key];
|
|
|
|
if (!Hash) {
|
|
|
|
var Buf = global.BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
|
|
|
|
Hash = global.shaarr(Buf);
|
|
|
|
glMapForHash[key] = Hash;
|
|
|
|
}
|
|
|
|
ArrRest.push(Hash);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
var Buf = global.BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
|
|
|
|
ArrRest.push(Buf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ArrRest;
|
|
|
|
};
|
|
|
|
var glMapRest = {};
|
|
|
|
|
|
|
|
function GetRestMerkleTree(BlockNumRest, RestIndexArr) {
|
|
|
|
var MerkleTree = glMapRest[BlockNumRest];
|
|
|
|
if (!MerkleTree) {
|
|
|
|
global.ToLog("Create new glMapRest key: " + BlockNumRest, 2);
|
|
|
|
var startTime = process.hrtime();
|
|
|
|
var EndAccount = global.DApps.Accounts.DBState.GetMaxNum();
|
|
|
|
var ArrHash = GetArrRest(BlockNumRest, 0, EndAccount, 1);
|
|
|
|
var Time1 = process.hrtime(startTime);
|
|
|
|
var MerkleCalc = {};
|
|
|
|
MerkleTree = { LevelsHash: [ArrHash], RecalcCount: 0 };
|
|
|
|
for (var Num = 0; Num < ArrHash.length; Num++) {
|
|
|
|
MerkleCalc[Num] = 1;
|
|
|
|
}
|
2019-07-10 07:59:04 +00:00
|
|
|
global.UpdateMerklTree(MerkleTree, MerkleCalc, 0);
|
2019-07-10 04:01:15 +00:00
|
|
|
glMapRest[BlockNumRest] = MerkleTree;
|
|
|
|
var Time2 = process.hrtime(startTime);
|
|
|
|
var deltaTime1 = (Time1[0] * 1000 + Time1[1] / 1e6) / 1000;
|
|
|
|
var deltaTime2 = (Time2[0] * 1000 + Time2[1] / 1e6) / 1000;
|
|
|
|
global.ToLog("Create delta time: " + deltaTime1 + "/" + deltaTime2 + " s Tree.Root=" + global.GetHexFromArr(MerkleTree.Root), 2);
|
|
|
|
var MapIndex = {};
|
|
|
|
for (var i = 0; i < RestIndexArr.length; i++) {
|
|
|
|
MapIndex[RestIndexArr[i]] = 1;
|
|
|
|
}
|
|
|
|
for (var key in glMapRest) {
|
|
|
|
if (!MapIndex[key]) {
|
|
|
|
global.ToLog("Delete old glMapRest key: " + key, 2);
|
|
|
|
delete glMapRest[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MerkleTree;
|
|
|
|
};
|