This commit is contained in:
progr76@gmail.com
2019-02-10 22:53:54 +03:00
parent 5b2c8d4ca1
commit 3029d69c0e
179 changed files with 56720 additions and 0 deletions

48
Source/process/dogs.js Normal file
View File

@@ -0,0 +1,48 @@
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
* @copyright: Yuriy Ivanov 2017-2019 [progr76@gmail.com]
* Web: https://terafoundation.org
* Twitter: https://twitter.com/terafoundation
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
*/
var lastcoin = 1000000000;
function show()
{
if(global.DApps && GENERATE_BLOCK_ACCOUNT)
{
var arr = DApps.Accounts.GetRowsAccounts(GENERATE_BLOCK_ACCOUNT, 1);
var Data = arr[0];
var sumcoin = Data.Value.SumCOIN;
var delta = sumcoin - lastcoin;
lastcoin = sumcoin;
if(delta > 200)
{
ToLog("ID:" + GENERATE_BLOCK_ACCOUNT);
if(global.COREY_WATCH_DOG === 1)
{
ToLog("Its forked restart now");
RestartNode();
}
else
if(global.COREY_WATCH_DOG === 2)
{
SERVER.FREE_ALL_MEM_CHAINS();
var Num = SERVER.BlockNumDB - 5000;
if(Num < 100)
Num = 100;
lastcoin = 1000000000;
ToLog("Its forked - truncate now from block: " + Num);
SERVER.SetTruncateBlockDB(Num);
}
}
}
};
if(global.COREY_WATCH_DOG)
{
ToLog("===START COREY_WATCH_DOG==");
setInterval(show, 35000);
}

View File

@@ -0,0 +1,882 @@
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
* @copyright: Yuriy Ivanov 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 = "MAIN";
const fs = require('fs');
const os = require('os');
require("../core/constant");
const crypto = require('crypto');
global.START_SERVER = 1;
global.DATA_PATH = GetNormalPathString(global.DATA_PATH);
global.CODE_PATH = GetNormalPathString(global.CODE_PATH);
console.log("DATA DIR: " + global.DATA_PATH);
console.log("PROGRAM DIR: " + global.CODE_PATH);
require("../core/library");
ToLog(os.platform() + " (" + os.arch() + ") " + os.release());
var VerArr = process.versions.node.split('.');
ToLog("nodejs: " + process.versions.node);
if(VerArr[0] < 8)
{
ToError("Error version of NodeJS=" + VerArr[0] + " Pls, download new version from www.nodejs.org and update it. The minimum version must be 8");
process.exit();
}
var CServer = require("../core/server");
setTimeout(function ()
{
TestSignLib(400);
}, 4000);
global.glCurNumFindArr = 0;
global.ArrReconnect = [];
global.ArrConnect = [];
var FindList = [{"ip":"91.235.136.81", "port":30005}, {"ip":"149.154.70.158", "port":30000}, ];
if(global.LOCAL_RUN)
{
FindList = [{"ip":"127.0.0.1", "port":50001}, {"ip":"127.0.0.1", "port":50002}];
}
else
if(global.TEST_NETWORK)
{
FindList = [{"ip":"149.154.70.158", "port":40000}, ];
}
global.SERVER = undefined;
global.NeedRestart = 0;
process.on('uncaughtException', function (err)
{
if(global.PROCESS_NAME !== "MAIN")
{
process.send({cmd:"log", message:err});
}
ToError(err.stack);
ToLog(err.stack);
if(err.code === "ENOTFOUND" || err.code === "ECONNRESET" || err.code === "EPIPE")
{
}
else
{
TO_ERROR_LOG("APP", 666, err);
ToLog("-----------------EXIT------------------");
process.exit();
}
});
process.on('error', function (err)
{
ToError(err.stack);
ToLog(err.stack);
});
var ArrChildProcess = [];
var WebProcess = {Name:"WEB PROCESS", idInterval:0, idInterval1:0, idInterval2:0, LastAlive:Date.now(), Worker:undefined, Path:"./process/web-process.js",
OnMessage:OnMessageWeb, PeriodAlive:3000};
if(global.HTTP_HOSTING_PORT && !global.NWMODE)
{
ArrChildProcess.push(WebProcess);
WebProcess.idInterval1 = setInterval(function ()
{
if(WebProcess.Worker && WebProcess.Worker.connected)
{
try
{
WebProcess.Worker.send({cmd:"Stat", Name:"MAX:ALL_NODES", Value:global.CountAllNode});
}
catch(e)
{
WebProcess.Worker = undefined;
}
}
}, 500);
WebProcess.idInterval2 = setInterval(function ()
{
if(WebProcess.Worker && WebProcess.Worker.connected)
{
var arr = SERVER.GetDirectNodesArray(true, true).slice(1, 500);
var arr2 = [];
var CurTime = GetCurrentTime() - 0;
for(var i = 0; i < SERVER.NodesArr.length; i++)
{
var Item = SERVER.NodesArr[i];
if(Item.LastTime && (CurTime - Item.LastTime) < 3600 * 1000)
arr2.push({ip:Item.ip});
else
if(Item.LastTimeGetNode && (CurTime - Item.LastTimeGetNode) < 3600 * 1000)
arr2.push({ip:Item.ip});
}
WebProcess.Worker.send({cmd:"NodeList", Value:arr, ValueAll:arr2});
}
}, 5000);
}
function OnMessageWeb(msg)
{
switch(msg.cmd)
{
case "SetSmartEvent":
{
if(global.TX_PROCESS && global.TX_PROCESS.Worker)
{
global.TX_PROCESS.Worker.send(msg);
}
break;
}
}
};
function AddTransactionFromWeb(HexValue)
{
var body = GetArrFromHex(HexValue);
if(global.TX_PROCESS && global.TX_PROCESS.Worker)
{
var StrHex = GetHexFromArr(sha3(body));
global.TX_PROCESS.Worker.send({cmd:"FindTX", TX:StrHex});
}
var Res = SERVER.AddTransaction({body:body}, 1);
var text = AddTrMap[Res];
var final = false;
if(Res <= 0 && Res !== - 3)
final = true;
ToLogClient("Send: " + text, GetHexFromArr(sha3(body)), final);
return text;
};
global.AddTransactionFromWeb = AddTransactionFromWeb;
global.STATIC_PROCESS = {Name:"STATIC PROCESS", idInterval:0, idInterval1:0, idInterval2:0, LastAlive:Date.now(), Worker:undefined,
Path:"./process/static-process.js", OnMessage:OnMessageStatic, PeriodAlive:3000};
ArrChildProcess.push(STATIC_PROCESS);
function OnMessageStatic(msg)
{
switch(msg.cmd)
{
case "Send":
{
var Node = SERVER.NodesMap[msg.addrStr];
if(Node)
{
msg.Data = msg.Data.data;
SERVER.Send(Node, msg, 1);
}
break;
}
}
};
global.TX_PROCESS = {Name:"TX PROCESS", idInterval:0, idInterval1:0, idInterval2:0, LastAlive:Date.now(), Worker:undefined,
Path:"./process/tx-process.js", OnMessage:OnMessageTX, PeriodAlive:100 * 1000};
ArrChildProcess.push(TX_PROCESS);
function OnMessageTX(msg)
{
switch(msg.cmd)
{
case "DappEvent":
{
if(WebProcess && WebProcess.Worker)
{
WebProcess.Worker.send(msg);
}
AddDappEventToGlobalMap(msg.Data);
break;
}
}
};
function StartAllProcess(bClose)
{
for(var i = 0; i < ArrChildProcess.length; i++)
{
var Item = ArrChildProcess[i];
StartChildProcess(Item);
}
if(bClose)
setInterval(function ()
{
if(global.DApps && DApps.Accounts)
{
DApps.Accounts.Close();
DApps.Smart.DBSmart.Close();
}
if(WALLET && WALLET.DBHistory)
WALLET.DBHistory.Close();
}, 500);
};
var GlobalRunID = 0;
var GlobalRunMap = {};
function StartChildProcess(Item)
{
let ITEM = Item;
ITEM.idInterval = setInterval(function ()
{
var Delta = Date.now() - ITEM.LastAlive;
if(ITEM.Worker && Delta > ITEM.PeriodAlive)
{
if(ITEM.Worker)
{
ToLog("KILL PROCESS " + ITEM.Name + ": " + ITEM.Worker.pid);
try
{
process.kill(ITEM.Worker.pid, 'SIGKILL');
}
catch(e)
{
}
ITEM.Worker = undefined;
}
}
try
{
ITEM.Worker.send({cmd:"Alive"});
}
catch(e)
{
ITEM.Worker = undefined;
}
if(!ITEM.Worker)
{
ITEM.LastAlive = (Date.now()) + ITEM.PeriodAlive * 3;
ToLog("STARTING " + ITEM.Name);
ITEM.Worker = Fork(ITEM.Path, ["READONLYDB"]);
ITEM.Worker.on('message', function (msg)
{
if(ITEM.LastAlive < Date.now())
ITEM.LastAlive = Date.now();
switch(msg.cmd)
{
case "call":
var Err = 0;
var Ret;
try
{
Ret = global[msg.Name](msg.Params);
}
catch(e)
{
Err = 1;
Ret = "" + e;
}
if(msg.id && ITEM.Worker)
ITEM.Worker.send({cmd:"retcall", id:msg.id, Err:Err, Params:Ret});
break;
case "retcall":
var F = GlobalRunMap[msg.id];
if(F)
{
delete GlobalRunMap[msg.id];
F(msg.Err, msg.Params);
}
break;
case "log":
ToLog(msg.message);
break;
case "ToLogClient":
if(WebProcess && WebProcess.Worker)
{
WebProcess.Worker.send(msg);
}
ToLogClient(msg.Str, msg.StrKey, msg.bFinal);
break;
case "online":
if(ITEM.Worker)
ToLog("RUNING " + ITEM.Name + " : " + msg.message + " pid: " + ITEM.Worker.pid);
break;
default:
if(ITEM.OnMessage)
{
ITEM.OnMessage(msg);
}
break;
}
});
}
}, 500);
ITEM.RunRPC = function (Name,Params,F)
{
if(!ITEM.Worker)
return ;
if(F)
{
GlobalRunID++;
try
{
ITEM.Worker.send({cmd:"call", id:GlobalRunID, Name:Name, Params:Params});
GlobalRunMap[GlobalRunID] = F;
}
catch(e)
{
}
}
else
{
ITEM.Worker.send({cmd:"call", id:0, Name:Name, Params:Params});
}
};
};
global.StopChildProcess = function ()
{
for(var i = 0; i < ArrChildProcess.length; i++)
{
var Item = ArrChildProcess[i];
if(Item.idInterval)
clearInterval(Item.idInterval);
Item.idInterval = 0;
if(Item.idInterval1)
clearInterval(Item.idInterval1);
Item.idInterval1 = 0;
if(Item.idInterval2)
clearInterval(Item.idInterval2);
Item.idInterval2 = 0;
if(Item.Worker && Item.Worker.connected)
{
Item.Worker.send({cmd:"Exit"});
Item.Worker = undefined;
}
}
RunStopPOWProcess("STOP");
};
require("../core/html-server");
RunServer();
setInterval(function run1()
{
DoConnectToNodes(ArrReconnect, "RECONNECT");
}, 200);
setInterval(function run2()
{
DoGetNodes();
DoConnectToNodes(ArrConnect, "CONNECT");
}, 500);
var StartCheckMining = 0;
global.MiningPaused = 0;
var ProcessMemorySize = 0;
global.ArrMiningWrk = [];
var BlockMining;
if(global.ADDRLIST_MODE)
{
return ;
}
function AllAlive()
{
for(var i = 0; i < ArrMiningWrk.length; i++)
{
ArrMiningWrk[i].send({cmd:"Alive"});
}
};
function ClearArrMining()
{
for(var i = 0; i < ArrMiningWrk.length; i++)
{
ArrMiningWrk[i].send({cmd:"Exit"});
}
ArrMiningWrk = [];
};
function RunStopPOWProcess(Mode)
{
if(!GetCountMiningCPU() || GetCountMiningCPU() <= 0)
return ;
if(!StartCheckMining)
{
StartCheckMining = 1;
setInterval(RunStopPOWProcess, CHECK_RUN_MINING);
setInterval(AllAlive, 1000);
}
if(global.NeedRestart)
return ;
if(global.USE_MINING && global.MINING_START_TIME && global.MINING_PERIOD_TIME)
{
var Time = GetCurrentTime();
var TimeCur = Time.getUTCHours() * 3600 + Time.getUTCMinutes() * 60 + Time.getUTCSeconds();
var StartTime = GetSecFromStrTime(global.MINING_START_TIME);
var RunPeriod = GetSecFromStrTime(global.MINING_PERIOD_TIME);
var TimeEnd = StartTime + RunPeriod;
global.MiningPaused = 1;
if(TimeCur >= StartTime && TimeCur <= TimeEnd)
{
global.MiningPaused = 0;
}
else
{
StartTime -= 24 * 3600;
TimeEnd -= 24 * 3600;
if(TimeCur >= StartTime && TimeCur <= TimeEnd)
{
global.MiningPaused = 0;
}
}
if(ArrMiningWrk.length && global.MiningPaused)
{
ToLog("------------ MINING MUST STOP ON TIME");
ClearArrMining();
return ;
}
else
if(!ArrMiningWrk.length && !global.MiningPaused)
{
ToLog("*********** MINING MUST START ON TIME");
}
else
{
return ;
}
}
else
{
global.MiningPaused = 0;
}
if(!global.USE_MINING || Mode === "STOP")
{
ClearArrMining();
return ;
}
if(global.USE_MINING && ArrMiningWrk.length)
return ;
if(SERVER.LoadHistoryMode)
return ;
if(GENERATE_BLOCK_ACCOUNT < 8)
return ;
var PathMiner = GetCodePath("../miner.js");
if(!fs.existsSync(PathMiner))
PathMiner = "./process/pow-process.js";
if(ArrMiningWrk.length >= GetCountMiningCPU())
return ;
if(GrayConnect())
{
ToLog("CANNOT START MINER IN NOT DIRECT IP MODE");
return ;
}
var Memory;
if(global.SIZE_MINING_MEMORY)
Memory = global.SIZE_MINING_MEMORY;
else
{
Memory = os.freemem() - (512 + GetCountMiningCPU() * 100) * 1024 * 1014;
if(Memory < 0)
{
ToLog("Not enough memory to start processes.");
return ;
}
}
ProcessMemorySize = Math.trunc(Memory / GetCountMiningCPU());
ToLog("START MINER PROCESS COUNT: " + GetCountMiningCPU() + " Memory: " + ProcessMemorySize / 1024 / 1024 + " Mb for eatch process");
for(var R = 0; R < GetCountMiningCPU(); R++)
{
let Worker = Fork(PathMiner);
ArrMiningWrk.push(Worker);
Worker.Num = ArrMiningWrk.length;
Worker.on('message', function (msg)
{
if(msg.cmd === "log")
{
ToLog(msg.message);
}
else
if(msg.cmd === "online")
{
Worker.bOnline = true;
ToLog("RUNING PROCESS:" + Worker.Num + ":" + msg.message);
}
else
if(msg.cmd === "POW")
{
SERVER.MiningProcess(msg);
}
else
if(msg.cmd === "HASHRATE")
{
ADD_HASH_RATE(msg.CountNonce);
}
});
Worker.on('error', function (err)
{
if(!ArrMiningWrk.length)
return ;
ToError('ERROR IN PROCESS: ' + err);
});
Worker.on('close', function (code)
{
ToLog("STOP PROCESS: " + Worker.Num + " pid:" + Worker.pid);
for(var i = 0; i < ArrMiningWrk.length; i++)
{
if(ArrMiningWrk[i].pid === Worker.pid)
{
ToLog("Delete wrk from arr - pid:" + Worker.pid);
ArrMiningWrk.splice(i, 1);
}
}
});
}
};
function SetCalcPOW(Block,cmd)
{
if(!global.USE_MINING)
return ;
if(ArrMiningWrk.length !== GetCountMiningCPU())
return ;
BlockMining = Block;
for(var i = 0; i < ArrMiningWrk.length; i++)
{
var CurWorker = ArrMiningWrk[i];
if(!CurWorker.bOnline)
continue;
CurWorker.send({cmd:cmd, BlockNum:Block.BlockNum, Account:GENERATE_BLOCK_ACCOUNT, MinerID:GENERATE_BLOCK_ACCOUNT, SeqHash:Block.SeqHash,
Hash:Block.Hash, PrevHash:Block.PrevHash, Time:Date.now(), Num:CurWorker.Num, RunPeriod:global.POWRunPeriod, RunCount:global.POW_RUN_COUNT,
RunCountFind:global.POW_RUN_COUNT_FIND, Percent:global.POW_MAX_PERCENT, CountMiningCPU:GetCountMiningCPU(), ProcessMemorySize:ProcessMemorySize,
});
}
};
global.SetCalcPOW = SetCalcPOW;
global.RunStopPOWProcess = RunStopPOWProcess;
function DoGetNodes()
{
if(!SERVER)
return ;
if(!GrayConnect() && SERVER.CanSend < 2)
return ;
if(!SERVER.NodesArrUnSort || !SERVER.NodesArrUnSort.length)
return ;
var Num = glCurNumFindArr % SERVER.NodesArrUnSort.length;
var Node = SERVER.NodesArrUnSort[Num];
if(Num === 0)
glCurNumFindArr = 0;
glCurNumFindArr++;
if(Node.Delete)
return ;
if(SERVER.NodeInBan(Node))
return ;
if(SERVER.BusyLevel && Node.BlockProcessCount <= SERVER.BusyLevel)
return ;
if(GetSocketStatus(Node.Socket) === 100)
{
SERVER.StartGetNodes(Node);
}
};
function DoConnectToNodes(Arr,Mode)
{
if(!SERVER)
return ;
if(!GrayConnect() && SERVER.CanSend < 2)
{
return ;
}
if(GrayConnect() && SERVER.ActualNodes.size > GetGrayServerConnections())
return ;
if(Arr.length)
{
var MinProcessCount = SERVER.BusyLevel - 1;
for(var i = 0; i < Arr.length; i++)
{
var Node = Arr[i];
if(Node.BlockProcessCount > MinProcessCount)
{
Arr.splice(i, 1);
if(Mode === "CONNECT")
{
Node.WasAddToConnect = undefined;
SERVER.StartConnectTry(Node);
}
else
if(Mode === "RECONNECT")
{
Node.WasAddToReconnect = undefined;
Node.CreateConnect();
}
break;
}
}
}
};
var idRunOnce;
function RunServer()
{
idRunOnce = setInterval(RunOnce, 1000);
ToLog("NETWORK: " + GetNetworkName());
ToLog("VERSION: " + DEF_VERSION);
if(global.NET_WORK_MODE)
{
global.START_IP = NET_WORK_MODE.ip;
global.START_PORT_NUMBER = NET_WORK_MODE.port;
}
var KeyPair = crypto.createECDH('secp256k1');
if(!global.SERVER_PRIVATE_KEY_HEX || global.NEW_SERVER_PRIVATE_KEY)
{
while(true)
{
var Arr = crypto.randomBytes(32);
KeyPair.setPrivateKey(Buffer.from(Arr));
var Arr2 = KeyPair.getPublicKey('', 'compressed');
if(Arr2[0] === 2)
break;
}
global.SERVER_PRIVATE_KEY_HEX = GetHexFromArr(Arr);
SAVE_CONST(true);
}
var ServerPrivKey = GetArrFromHex(global.SERVER_PRIVATE_KEY_HEX);
if(global.USE_NET_FOR_SERVER_ADDRES)
{
const os = require('os');
var map = os.networkInterfaces();
main:
for(var key in map)
{
var arr = map[key];
for(var i = 0; i < arr.length; i++)
{
var item = arr[i];
if(!item.internal && item.mac !== "00:00:00:00:00:00")
{
ServerPrivKey = sha3(global.SERVER_PRIVATE_KEY_HEX + ":" + item.mac + ":" + global.START_PORT_NUMBER);
break main;
}
}
}
}
KeyPair.setPrivateKey(Buffer.from(ServerPrivKey));
new CServer(KeyPair, START_IP, START_PORT_NUMBER, false, false);
DoStartFindList();
};
function DoStartFindList()
{
var keyThisServer = SERVER.ip + ":" + SERVER.port;
for(var n = 0; n < FindList.length; n++)
{
var item = FindList[n];
if(!item.ip)
continue;
var key = item.ip + ":" + item.port;
if(keyThisServer === key)
continue;
var addrStr = GetHexFromAddres(crypto.randomBytes(32));
var Node = SERVER.GetNewNode(addrStr, item.ip, item.port);
Node.addrStrTemp = addrStr;
Node.StartFindList = 1;
}
};
function RunOnce()
{
if(global.SERVER && global.SERVER.CheckOnStartComplete)
{
clearInterval(idRunOnce);
RunOnUpdate();
StartAllProcess(1);
require("./dogs");
if(global.RESTART_PERIOD_SEC)
{
var Period = (random(600) + global.RESTART_PERIOD_SEC);
ToLog("SET RESTART NODE AFTER: " + Period + " sec");
setInterval(function ()
{
RestartNode();
}, Period * 1000);
}
setTimeout(function ()
{
RunStopPOWProcess();
}, 10000);
}
};
function RunOnUpdate()
{
if(!UPDATE_NUM_COMPLETE)
UPDATE_NUM_COMPLETE = 0;
var CurNum = UPDATE_NUM_COMPLETE;
if(CurNum !== UPDATE_CODE_VERSION_NUM)
{
global.UPDATE_NUM_COMPLETE = UPDATE_CODE_VERSION_NUM;
ToLog("UPDATER Start");
SAVE_CONST(true);
if(global.TEST_NETWORK)
{
}
else
{
}
ToLog("UPDATER Finish");
}
};
function CheckRewriteTr(Num,StrHash,StartRewrite)
{
if(SERVER.BlockNumDB < StartRewrite)
return "NO";
var AccountsHash = DApps.Accounts.GetHashOrUndefined(Num);
if(!AccountsHash || GetHexFromArr(AccountsHash) !== StrHash)
{
ToLog("START REWRITE ERR ACTS TRANSACTIONS");
SERVER.ReWriteDAppTransactions(SERVER.BlockNumDB - StartRewrite);
return "Rewrite";
}
else
{
return "OK";
}
};
function CheckRewriteAllTr2(Num,StrHash,Num2,StrHash2)
{
if(global.LOCAL_RUN || global.TEST_NETWORK)
return "NONE";
var MaxNum = SERVER.GetMaxNumBlockDB();
if(MaxNum < START_BLOCK_ACCOUNT_HASH)
return "NONE";
var AccountsHash = DApps.Accounts.GetHashOrUndefined(Num);
var AccountsHash2 = DApps.Accounts.GetHashOrUndefined(Num2);
if(AccountsHash2 && GetHexFromArr(AccountsHash2) === StrHash2)
return "OK";
if(AccountsHash && GetHexFromArr(AccountsHash) !== StrHash)
{
ToLog("***************** START REWRITE ALL DAPPS");
global.UpdateMode = 1;
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
global.UpdateMode = 0;
return "Rewrite";
}
else
{
return "OK";
}
};
function CheckRewriteAllTr(Num,StrHash,Num2,StrHash2)
{
if(global.LOCAL_RUN || global.TEST_NETWORK)
return "NONE";
var MaxNum = SERVER.GetMaxNumBlockDB();
if(MaxNum < START_BLOCK_ACCOUNT_HASH)
return "NONE";
var AccountsHash = DApps.Accounts.GetHashOrUndefined(Num);
if(AccountsHash && GetHexFromArr(AccountsHash) !== StrHash)
{
ToLog("***************** START REWRITE ALL DAPPS");
global.UpdateMode = 1;
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
global.UpdateMode = 0;
return "Rewrite";
}
else
{
return "OK";
}
};
global.CheckRewriteTr = CheckRewriteTr;
var glPortDebug = 49800;
function Fork(Path,ArrArgs)
{
const child_process = require('child_process');
ArrArgs = ArrArgs || [];
if(global.LOCAL_RUN)
ArrArgs.push("LOCALRUN");
else
if(global.TEST_NETWORK)
ArrArgs.push("TESTRUN");
ArrArgs.push("PATH:" + global.DATA_PATH);
ArrArgs.push("HOSTING:" + global.HTTP_HOSTING_PORT);
if(!global.USE_PARAM_JS)
ArrArgs.push("NOPARAMJS");
if(global.NWMODE)
ArrArgs.push("NWMODE");
if(global.NOALIVE)
ArrArgs.push("NOALIVE");
if(global.DEV_MODE)
ArrArgs.push("DEV_MODE");
glPortDebug++;
var execArgv = [];
var Worker = child_process.fork(Path, ArrArgs, {execArgv:execArgv});
return Worker;
};
function FixBlockBug12970020()
{
var Block = SERVER.ReadBlockHeaderDB(12970020);
if(!Block)
return ;
CorrectBlockBug12970020(Block);
var BufWrite = BufLib.GetNewBuffer(BLOCK_HEADER_SIZE);
SERVER.BlockHeaderToBuf(BufWrite, Block);
var Ret = SERVER.WriteBufHeaderDB(BufWrite, Block.BlockNum);
return Ret;
};
function CorrectBlockBug12970020(Block)
{
Block.TreeHash = GetArrFromHex("9FE0A443BD42E70206133119D6D13638D422E34BD5CC38A7A12368EB4A8A1D4F");
CreateHashMinimal(Block, 0);
Block.SumPow = 367146128;
};
function RecreateAccountHashDB()
{
var name = "accounts-hash";
var fname = GetDataPath("DB/" + name);
if(fs.existsSync(fname))
{
global.UpdateMode = 1;
ToLog("Start updating " + name);
const DBRow = require("../core/db/db-row");
var DB0 = new DBRow(name, 6 + 32 + 12, "{BlockNum:uint,Hash:hash, Reserve: arr12}");
var DB2 = DApps.Accounts.DBAccountsHash;
for(var num = START_BLOCK_ACCOUNT_HASH; true; num += PERIOD_ACCOUNT_HASH)
{
var Item = DB0.Read(num);
if(!Item)
break;
var Block = SERVER.ReadBlockHeaderDB(num);
if(!Block)
break;
var Data = {Num:Block.BlockNum / PERIOD_ACCOUNT_HASH, BlockNum:Block.BlockNum, Hash:Item.Hash, SumHash:Block.SumHash};
DB2.Write(Data);
DB2.Truncate(Block.BlockNum / PERIOD_ACCOUNT_HASH);
}
ToLog("Finish updating " + name);
DB0.Close();
DB2.Close();
global.UpdateMode = 0;
fs.unlinkSync(fname);
}
};
global.TestSignLib = TestSignLib;
function TestSignLib(MaxTime)
{
var hash = Buffer.from(GetArrFromHex("A6B0914953F515F4686B2BA921B8FAC66EE6A6D3E317B43E981EBBA52393BFC6"));
var PubKey = Buffer.from(GetArrFromHex("026A04AB98D9E4774AD806E302DDDEB63BEA16B5CB5F223EE77478E861BB583EB3"));
var Sign = Buffer.from(GetArrFromHex("5D5382C65E4C1E8D412D5F30F87B8F72F371E9E4FC170761BCE583A961CF44966F92B38D402BC1CBCB7567335051A321B93F4E32112129AED4AB602E093A1187"));
var startTime = process.hrtime();
for(var Num = 0; Num < 1000; Num++)
{
var Result = secp256k1.verify(hash, Sign, PubKey);
if(!Result)
{
ToError("Error test sign");
process.exit(0);
}
var Time = process.hrtime(startTime);
var deltaTime = Time[0] * 1000 + Time[1] / 1e6;
if(deltaTime > MaxTime)
{
ToLog("*************** WARNING: VERY SLOW LIBRARY: secp256k1 ***************");
ToLog("You can only process: " + Num + " transactions");
ToLog("Install all dependent packages and run the installation command:\ncd Source/node_modules/secp256k1 \nnode-gyp build");
return 0;
}
}
ToLog("TestSignLib: " + Math.trunc(deltaTime) + " ms");
return 1;
};

View File

@@ -0,0 +1,97 @@
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
* @copyright: Yuriy Ivanov 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 = "POW", global.POWPROCESS = 1, require("../core/library"), require("../core/crypto-library"), require("../core/terahashmining");
var PROCESS = process;
process.send && !global.DEBUGPROCESS ? process.send({cmd:"online", message:"OK"}) : PROCESS = global.DEBUGPROCESS;
var LastAlive = Date.now();
setInterval(CheckAlive, 1e3);
var idInterval = void 0, Block = {};
function CheckAlive()
{
if(!global.NOALIVE)
{
var e = Date.now() - LastAlive;
Math.abs(e) > CHECK_STOP_CHILD_PROCESS && PROCESS.exit(0);
}
};
function CalcPOWHash()
{
if(Block.SeqHash)
{
if(new Date - Block.Time > Block.Period)
return clearInterval(idInterval), void (idInterval = void 0);
try
{
CreatePOWVersionX(Block) && process.send({cmd:"POW", BlockNum:Block.BlockNum, SeqHash:Block.SeqHash, Hash:Block.Hash, PowHash:Block.PowHash,
AddrHash:Block.AddrHash, Num:Block.Num});
}
catch(e)
{
ToError(e);
}
}
};
PROCESS.on("message", function (e)
{
if(LastAlive = Date.now(), "FastCalcBlock" === e.cmd)
{
var o = e;
StartHashPump(o), o.RunCount = 0;
try
{
CreatePOWVersionX(o) && process.send({cmd:"POW", BlockNum:o.BlockNum, SeqHash:o.SeqHash, Hash:o.Hash, PowHash:o.PowHash, AddrHash:o.AddrHash,
Num:o.Num});
}
catch(e)
{
ToError(e);
}
}
else
if("SetBlock" === e.cmd)
{
var a = 1e6 * (1 + e.Num);
Block.HashCount && process.send({cmd:"HASHRATE", CountNonce:Block.HashCount, Hash:Block.Hash}), Block.HashCount = 0, (Block = e).Time = Date.now(),
Block.LastNonce = a, Block.Period = CONSENSUS_PERIOD_TIME * Block.Percent / 100, 0 < Block.Period && 0 < Block.RunPeriod && (CalcPOWHash(),
void 0 !== idInterval && clearInterval(idInterval), idInterval = setInterval(CalcPOWHash, Block.RunPeriod));
}
else
"Alive" === e.cmd || "Exit" === e.cmd && PROCESS.exit(0);
});
var idIntervalPump = global.BlockPump = void 0;
function StartHashPump(e)
{
(!BlockPump || BlockPump.BlockNum < e.BlockNum || BlockPump.MinerID !== e.MinerID || BlockPump.Percent !== e.Percent) && (global.BlockPump = {BlockNum:e.BlockNum,
RunCount:e.RunCount, MinerID:e.MinerID, Percent:e.Percent, LastNonce:0, RunCountFind:0}), idIntervalPump || (idIntervalPump = setInterval(PumpHash,
global.POWRunPeriod));
};
var StartTime = 1, EndTime = 0;
function PumpHash()
{
if(BlockPump)
{
var e = Date.now();
if(EndTime < StartTime)
{
if(100 * (e - StartTime) / CONSENSUS_PERIOD_TIME >= BlockPump.Percent)
return void (EndTime = e);
CreatePOWVersionX(BlockPump, 1);
}
else
{
100 * (e - EndTime) / CONSENSUS_PERIOD_TIME > 100 - BlockPump.Percent && (StartTime = e);
}
}
};

View File

@@ -0,0 +1,202 @@
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
* @copyright: Yuriy Ivanov 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");
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;
}
});
function CheckAlive()
{
if(global.NOALIVE)
return ;
var Delta = Date.now() - LastAlive;
if(Delta > CHECK_STOP_CHILD_PROCESS)
{
ToLog("STAIC-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("STAIC-DB", 777, err);
ToLog("-----------------STAIC-DB EXIT------------------");
process.exit();
});
process.on('error', function (err)
{
ToError("STAIC-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();
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)
{
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});
};
const Formats = {BLOCK_TRANSFER:"{\
BlockNum:uint,\
TreeHash:hash,\
arrContent:[tr],\
}",
WRK_BLOCK_TRANSFER:{}, };
function GETBLOCK(msg)
{
var Data = msg.Data;
var BlockNum = Data.BlockNum;
var TreeHash = Data.TreeHash;
if(msg.Context.SendCount)
{
return ;
}
var BufWrite;
var BlockDB = undefined;
if(TreeHash && !IsZeroArr(TreeHash))
{
BlockDB = SERVER.ReadBlockDB(BlockNum);
}
var StrSend;
if(BlockDB && CompareArr(BlockDB.TreeHash, TreeHash) === 0)
{
var BufWrite = BufLib.GetBufferFromObject(BlockDB, Formats.BLOCK_TRANSFER, MAX_PACKET_LENGTH, Formats.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});
}
};

View File

@@ -0,0 +1,288 @@
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
* @copyright: Yuriy Ivanov 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 = "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":
global.TreeFindTX.SaveValue(msg.TX, msg.TX);
break;
case "SetSmartEvent":
global.TreeFindTX.SaveValue("Smart:" + msg.Smart, 1);
break;
case "RewriteAllTransactions":
RewriteAllTransactions(msg);
break;
case "ReWriteDAppTransactions":
ReWriteDAppTransactions(msg);
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)
{
ToLog("TX-PROCESS: 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("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;
var LastBlockNum = undefined;
function DoTXProcess()
{
if(LastBlockNum === undefined)
InitTXProcess();
var BlockMin = FindMinimal();
if(!BlockMin)
{
return ;
}
var StartTime = Date.now();
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)
{
break;
}
if(!IsValidSumHash(Block))
{
break;
}
var Item = BlockTree.LoadValue(Block.BlockNum, 1);
if(Item && CompareArr(Item.SumHash, Block.SumHash) === 0)
{
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();
}
for(var Num = LastBlockNum; Num--; Num > 0)
{
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;
}
RewriteAllTransactions();
Block = SERVER.ReadBlockHeaderDB(0);
return Block;
};
function IsValidSumHash(Block)
{
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;
}
}
ToLog("DETECT NEW VER on BlockNum=" + LastBlockNum);
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum});
}
StateTX = DApps.Accounts.DBStateTX.Read(0);
LastBlockNum = StateTX.BlockNum;
LastBlockNum = PERIOD_ACCOUNT_HASH * Math.trunc(LastBlockNum / PERIOD_ACCOUNT_HASH);
if(LastBlockNum > 100)
{
LastBlockNum = 1 + LastBlockNum - 100;
}
if(LastBlockNum <= 0)
RewriteAllTransactions();
else
ToLog("Start NUM = " + LastBlockNum);
DApps.Accounts.CalcMerkleTree();
};
function RewriteAllTransactions()
{
ToLog("*************RewriteAllTransactions");
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
LastBlockNum = 0;
BlockTree.Clear();
ToLog("Start num = " + LastBlockNum);
};
function ReWriteDAppTransactions(msg)
{
var StartNum = msg.StartNum;
var EndNum = msg.EndNum;
ToLog("ReWriteDAppTransactions: " + StartNum + " - " + EndNum);
BlockTree.Clear();
if(StartNum < LastBlockNum)
LastBlockNum = StartNum;
ToLog("Start num = " + LastBlockNum);
};
global.EvalCode = function (Code)
{
var Result;
try
{
var ret = eval(Code);
Result = JSON.stringify(ret, "", 4);
}
catch(e)
{
Result = "" + e;
}
return Result;
};

View File

@@ -0,0 +1,747 @@
/*
* @project: TERA
* @version: Development (beta)
* @license: MIT (not for evil)
* @copyright: Yuriy Ivanov 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 = "WEB";
const crypto = require('crypto');
const http = require('http'), net = require('net'), url = require('url'), fs = require('fs'), querystring = require('querystring');
global.MAX_STAT_PERIOD = 60;
require("../core/constant");
global.MAX_STAT_PERIOD = 60;
global.DATA_PATH = GetNormalPathString(global.DATA_PATH);
global.CODE_PATH = GetNormalPathString(global.CODE_PATH);
require("../core/library");
require("../core/geo");
global.READ_ONLY_DB = 1;
global.MAX_STAT_PERIOD = 60;
var HostNodeList = [];
var AllNodeList = [];
var NodeBlockChain = [];
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 "retcall":
var F = GlobalRunMap[msg.id];
if(F)
{
delete GlobalRunMap[msg.id];
F(msg.Err, msg.Params);
}
break;
case "Stat":
ADD_TO_STAT(msg.Name, msg.Value);
break;
case "NodeList":
HostNodeList = msg.Value;
AllNodeList = msg.ValueAll;
break;
case "NodeBlockChain":
NodeBlockChain = msg.Value;
break;
case "DappEvent":
{
AddDappEventToGlobalMap(msg.Data);
break;
}
case "ToLogClient":
{
ToLogClient0(msg.Str, msg.StrKey, msg.bFinal);
break;
}
}
});
function CheckAlive()
{
if(global.NOALIVE)
return ;
var Delta = Date.now() - LastAlive;
if(Delta > CHECK_STOP_CHILD_PROCESS)
{
ToLog("HOSTING: 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("HOSTING", 777, err);
ToLog("-----------------HOSTING EXIT------------------");
process.exit();
});
process.on('error', function (err)
{
ToError("HOSTING:\n" + err.stack);
ToLog(err.stack);
});
if(!global.HTTP_HOSTING_PORT)
{
ToLogTrace("global.HTTP_HOSTING_PORT=" + global.HTTP_HOSTING_PORT);
process.exit();
}
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;
require("../core/html-server");
require("../core/transaction-validator");
global.STAT_MODE = 1;
setInterval(PrepareStatEverySecond, 1000);
var HostingServer;
if(global.HTTPS_HOSTING_DOMAIN)
{
var file_sert = GetDataPath("sertif.lst");
CheckCreateDir(GetDataPath("tmp"));
var greenlock = require('greenlock').create({version:'draft-12', server:'https://acme-v02.api.letsencrypt.org/directory', configDir:GetDataPath('tmp'),
});
var redir = require('redirect-https')();
require('http').createServer(greenlock.middleware(redir)).listen(80);
var GetNewSert = 1;
if(fs.existsSync(file_sert))
{
var certs = LoadParams(file_sert, {});
var Delta = certs.expiresAt - Date.now();
if(Delta > 7 * 86000 * 1000)
{
ToLog("USE OLD SERT. ExpiresAt: " + new Date(certs.expiresAt));
GetNewSert = 0;
var tlsOptions = {key:certs.privkey, cert:certs.cert + '\r\n' + certs.chain};
HostingServer = require('https').createServer(tlsOptions, MainHTTPFunction);
RunListenServer();
}
}
if(GetNewSert)
{
ToLog("Start get new SERT");
var opts = {domains:[global.HTTPS_HOSTING_DOMAIN], email:'progr76@gmail.com', agreeTos:true, communityMember:true, };
greenlock.register(opts).then(function (certs)
{
SaveParams(file_sert, certs);
var tlsOptions = {key:certs.privkey, cert:certs.cert + '\r\n' + certs.chain};
HostingServer = require('https').createServer(tlsOptions, MainHTTPFunction);
RunListenServer();
}, function (err)
{
ToError(err);
});
}
}
else
{
HostingServer = http.createServer(MainHTTPFunction);
RunListenServer();
}
function MainHTTPFunction(request,response)
{
if(!request.socket || !request.socket.remoteAddress)
return ;
SetSafeResponce(response);
var DataURL = url.parse(request.url);
var Params = querystring.parse(DataURL.query);
var Path = querystring.unescape(DataURL.pathname);
var Type = request.method;
if(Type === "POST")
{
let Response = response;
let postData = "";
request.addListener("data", function (postDataChunk)
{
if(postData.length <= 12000 && postDataChunk.length <= 12000)
postData += postDataChunk;
else
{
var Str = "Error postDataChunk.length=" + postDataChunk.length;
ToLog(Str);
Response.writeHead(405, {'Content-Type':'text/html'});
Response.end(Str);
}
});
request.addListener("end", function ()
{
var Data;
if(postData && postData.length)
{
try
{
Data = JSON.parse(postData);
}
catch(e)
{
Response.writeHead(405, {'Content-Type':'text/html'});
Response.end("Error data parsing");
}
}
DoCommandNew(response, Type, Path, Data);
});
}
else
{
DoCommandNew(response, Type, Path, Params);
}
};
var bWasRun = 0;
function RunListenServer()
{
HostingServer.on('error', function (err)
{
if(err.code === 'EADDRINUSE')
{
ToLogClient('Port ' + global.HTTP_HOSTING_PORT + ' in use, retrying...');
if(HostingServer.Server)
HostingServer.Server.close();
setTimeout(function ()
{
RunListenServer();
}, 5000);
return ;
}
ToError("H##6");
ToError(err);
});
ToLogClient("Prepare to run WEB-server on port: " + global.HTTP_HOSTING_PORT);
HostingServer.listen(global.HTTP_HOSTING_PORT, '0.0.0.0', function ()
{
if(!bWasRun)
ToLogClient("Run WEB-server on port: " + global.HTTP_HOSTING_PORT);
bWasRun = 1;
});
};
var WalletFileMap = {};
WalletFileMap["coinlib.js"] = 1;
WalletFileMap["client.js"] = 1;
WalletFileMap["diagram.js"] = 1;
WalletFileMap["sha3.js"] = 1;
WalletFileMap["terahashlib.js"] = 1;
WalletFileMap["wallet-web.js"] = 1;
WalletFileMap["wallet-lib.js"] = 1;
WalletFileMap["crypto-client.js"] = 1;
WalletFileMap["dapp-inner.js"] = 1;
WalletFileMap["marked.js"] = 1;
WalletFileMap["highlight.js"] = 1;
WalletFileMap["highlight-js.js"] = 1;
WalletFileMap["highlight-html.js"] = 1;
WalletFileMap["codes.css"] = 1;
WalletFileMap["sign-lib-min.js"] = 1;
WalletFileMap["buttons.css"] = 1;
WalletFileMap["style.css"] = 1;
WalletFileMap["wallet.css"] = 1;
WalletFileMap["blockviewer.html"] = 1;
WalletFileMap["web-wallet.html"] = 1;
global.HostingCaller = {};
function DoCommandNew(response,Type,Path,Params)
{
if(Path.substring(0, 1) === "/")
Path = Path.substring(1);
var ArrPath = Path.split('/', 3);
var Method = ArrPath[0];
var F = HostingCaller[Method];
if(F)
{
response.writeHead(200, {'Content-Type':'text/plain', 'Access-Control-Allow-Origin':"*"});
var Ret = F(Params, response);
if(Ret === null)
return ;
try
{
var Str;
if(typeof Ret === "object")
Str = JSON.stringify(Ret);
else
Str = Ret;
response.end(Str);
}
catch(e)
{
ToLog("ERR PATH:" + Path);
ToLog(e);
response.end();
}
return ;
}
Method = Method.toLowerCase();
if(Method === "dapp" && ArrPath.length === 2)
Method = "DappTemplateFile";
switch(Method)
{
case "":
SendWebFile(response, "./SITE/index.html", undefined, true);
break;
case "file":
SendBlockFile(response, ArrPath[1], ArrPath[2]);
break;
case "DappTemplateFile":
DappTemplateFile(response, ArrPath[1]);
break;
case "smart":
DappSmartCodeFile(response, ArrPath[1]);
break;
default:
{
var Name = ArrPath[ArrPath.length - 1];
if(typeof Name !== "string")
Name = "ErrorPath";
else
if(Name.indexOf("..") >= 0 || Name.indexOf("\\") >= 0 || Name.indexOf("/") >= 0)
Name = "ErrorFilePath";
if(Name.indexOf(".") < 0)
Name += ".html";
var PrefixPath;
if(Method === "files")
{
PrefixPath = "../FILES";
Name = PrefixPath + "/" + Name;
SendWebFile(response, Name, Path);
return ;
}
else
if(WalletFileMap[Name])
PrefixPath = "./HTML";
else
PrefixPath = "./SITE";
var type = Path.substr(Path.length - 3, 3);
switch(type)
{
case ".js":
Name = PrefixPath + "/JS/" + Name;
break;
case "css":
Name = PrefixPath + "/CSS/" + Name;
break;
case "wav":
case "mp3":
Name = PrefixPath + "/SOUND/" + Name;
break;
case "svg":
case "png":
case "gif":
case "jpg":
case "ico":
Name = PrefixPath + "/PIC/" + Name;
break;
case "pdf":
case "zip":
case "exe":
case "msi":
Name = PrefixPath + "/FILES/" + Name;
break;
default:
Name = PrefixPath + "/" + Name;
break;
}
SendWebFile(response, Name, Path);
break;
}
}
};
HostingCaller.GetCurrentInfo = function (Params)
{
var Ret = {result:1, VersionNum:global.UPDATE_CODE_VERSION_NUM, MaxNumBlockDB:SERVER.GetMaxNumBlockDB(), CurBlockNum:GetCurrentBlockNumByTime(),
MaxAccID:DApps.Accounts.GetMaxAccount(), MaxDappsID:DApps.Smart.GetMaxNum(), NETWORK:global.NETWORK, CurTime:Date.now(), DELTA_CURRENT_TIME:DELTA_CURRENT_TIME,
MIN_POWER_POW_TR:MIN_POWER_POW_TR, FIRST_TIME_BLOCK:FIRST_TIME_BLOCK, CONSENSUS_PERIOD_TIME:CONSENSUS_PERIOD_TIME, MIN_POWER_POW_ACC_CREATE:MIN_POWER_POW_ACC_CREATE,
};
if(typeof Params === "object" && Params.Diagram == 1)
{
var arrNames = ["MAX:ALL_NODES", "MAX:HASH_RATE_G"];
Ret.arr = GET_STATDIAGRAMS(arrNames);
}
if(typeof Params === "object" && Params.BlockChain == 1)
{
Ret.BlockChain = NodeBlockChain;
}
if(typeof Params === "object" && Params.ArrLog == 1)
{
var ArrLog = [];
for(var i = 0; i < ArrLogClient.length; i++)
{
var Item = ArrLogClient[i];
if(!Item.final)
continue;
ArrLog.push(Item);
}
Ret.ArrLog = ArrLog;
}
return Ret;
};
var MaxCountViewRows = global.HTTP_MAX_COUNT_ROWS;
HostingCaller.GetAccountList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = DApps.Accounts.GetRowsAccounts(ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {result:1, arr:arr};
};
HostingCaller.GetAccount = function (id)
{
id = ParseNum(id);
var arr = DApps.Accounts.GetRowsAccounts(id, 1);
return {Item:arr[0], result:1};
};
HostingCaller.GetBlockList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = SERVER.GetRows(ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {result:1, arr:arr};
};
HostingCaller.GetTransactionList = function (Params)
{
return HostingCaller.GetTransactionAll(Params);
};
HostingCaller.GetTransactionAll = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
if(Params.Param3)
Params.BlockNum = Params.Param3;
var arr = SERVER.GetTrRows(ParseNum(Params.BlockNum), ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {result:1, arr:arr};
};
HostingCaller.GetDappList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = DApps.Smart.GetRows(ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {result:1, arr:arr};
};
HostingCaller.GetNodeList = function (Params)
{
var arr = [];
var List;
if(typeof Params === "object" && Params.All)
List = AllNodeList;
else
List = HostNodeList;
var MaxNodes = 20;
var len = List.length;
var UseRandom = 0;
if(len > MaxNodes)
{
UseRandom = 1;
len = MaxNodes;
}
var mapWasAdd = {};
for(var i = 0; i < len; i++)
{
var Item;
if(UseRandom)
{
var num = random(List.length);
Item = List[num];
if(mapWasAdd[Item.ip])
{
continue;
}
mapWasAdd[Item.ip] = 1;
}
else
{
Item = List[i];
}
var Value = {ip:Item.ip, port:Item.portweb, };
if(typeof Params === "object" && Params.Geo)
{
if(!Item.Geo)
SetGeoLocation(Item);
Value.latitude = Item.latitude;
Value.longitude = Item.longitude;
Value.name = Item.name;
}
arr.push(Value);
}
return {result:1, arr:arr};
};
var AccountKeyMap = {};
var LastMaxNum = 0;
HostingCaller.GetAccountListByKey = function (Params,ppp,bRet)
{
if(typeof Params !== "object" || !Params.Key)
return {result:0, arr:[]};
var Accounts = DApps.Accounts;
for(var num = LastMaxNum; true; num++)
{
if(Accounts.IsHole(num))
continue;
var Data = Accounts.ReadState(num);
if(!Data)
break;
var StrKey = GetHexFromArr(Data.PubKey);
Data.Next = AccountKeyMap[StrKey];
AccountKeyMap[StrKey] = Data;
}
LastMaxNum = num;
var arr = [];
var Item = AccountKeyMap[Params.Key];
while(Item)
{
var Data = Accounts.ReadState(Item.Num);
if(!Data)
continue;
if(!Data.PubKeyStr)
Data.PubKeyStr = GetHexFromArr(Data.PubKey);
if(Data.Currency)
Data.CurrencyObj = DApps.Smart.ReadSimple(Data.Currency);
if(Data.Value.Smart)
{
Data.SmartObj = DApps.Smart.ReadSimple(Data.Value.Smart);
try
{
Data.SmartState = BufLib.GetObjectFromBuffer(Data.Value.Data, Data.SmartObj.StateFormat, {});
if(typeof Data.SmartState === "object")
Data.SmartState.Num = Item.Num;
}
catch(e)
{
Data.SmartState = {};
}
}
arr.unshift(Data);
Item = Item.Next;
if(arr.length >= 30)
break;
}
var Ret = {result:1, arr:arr};
if(bRet)
return Ret;
var Context = GetUserContext(Params);
var StrInfo = JSON.stringify(Ret);
if(!Params.AllData && Context.PrevAccountList === StrInfo)
{
return {result:0, cache:1};
}
Context.PrevAccountList = StrInfo;
Context.NumAccountList++;
return StrInfo;
};
HostingCaller.SendTransactionHex = function (Params,response)
{
if(typeof Params !== "object" || !Params.Hex)
return {result:0, text:"object requre"};
process.RunRPC("AddTransactionFromWeb", Params.Hex, function (Err,text)
{
var Result = {result:!Err, text:text};
var Str = JSON.stringify(Result);
response.end(Str);
});
return null;
};
HostingCaller.DappSmartHTMLFile = function (Params)
{
if(typeof Params !== "object")
return {result:0};
return HTTPCaller.DappSmartHTMLFile(Params);
};
HostingCaller.DappBlockFile = function (Params)
{
if(typeof Params !== "object")
return {result:0};
return HTTPCaller.DappBlockFile(Params);
};
HostingCaller.DappInfo = function (Params)
{
if(typeof Params !== "object")
return {result:0};
var SmartNum = ParseNum(Params.Smart);
process.send({cmd:"SetSmartEvent", Smart:SmartNum});
var Context = GetUserContext(Params);
var Ret = HTTPCaller.DappInfo(Params, undefined, 1);
Ret.PubKey = undefined;
var StrInfo = JSON.stringify(Ret);
if(!Params.AllData && Context.PrevDappInfo === StrInfo)
{
return {result:0, cache:1};
}
Context.PrevDappInfo = StrInfo;
Context.NumDappInfo++;
Context.LastTime = Date.now();
Ret.NumDappInfo = Context.NumDappInfo;
Ret.CurTime = Date.now();
Ret.CurBlockNum = GetCurrentBlockNumByTime();
Ret.BlockNumDB = SERVER.BlockNumDB;
Ret.MaxAccID = DApps.Accounts.GetMaxAccount();
Ret.MaxDappsID = DApps.Smart.GetMaxNum();
return Ret;
};
HostingCaller.DappWalletList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
var Ret = HostingCaller.GetAccountListByKey(Params, undefined, 1);
var Smart = ParseNum(Params.Smart);
var arr = [];
for(var i = 0; i < Ret.arr.length; i++)
{
if(Ret.arr[i].Value.Smart === Smart || Params.AllAccounts)
{
arr.push(Ret.arr[i]);
}
}
Ret.arr = arr;
return Ret;
};
HTTPCaller.DappWalletList = HostingCaller.DappWalletList;
HostingCaller.DappAccountList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = DApps.Accounts.GetRowsAccounts(ParseNum(Params.StartNum), ParseNum(Params.CountNum), undefined, 1);
return {arr:arr, result:1};
};
HostingCaller.DappSmartList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = DApps.Smart.GetRows(ParseNum(Params.StartNum), ParseNum(Params.CountNum), undefined, undefined, Params.GetAllData,
Params.TokenGenerate);
return {arr:arr, result:1};
};
HostingCaller.DappBlockList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = SERVER.GetRows(ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {arr:arr, result:1};
};
HostingCaller.DappTransactionList = function (Params)
{
if(typeof Params !== "object")
return {result:0};
if(Params.CountNum > MaxCountViewRows)
Params.CountNum = MaxCountViewRows;
if(!Params.CountNum)
Params.CountNum = 1;
var arr = SERVER.GetTrRows(ParseNum(Params.BlockNum), ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {arr:arr, result:1};
};
HostingCaller.DappStaticCall = function (Params)
{
if(typeof Params !== "object")
return {result:0};
return HTTPCaller.DappStaticCall(Params);
};
var GlobalRunID = 0;
var GlobalRunMap = {};
process.RunRPC = function (Name,Params,F)
{
if(F)
{
GlobalRunID++;
try
{
process.send({cmd:"call", id:GlobalRunID, Name:Name, Params:Params});
GlobalRunMap[GlobalRunID] = F;
}
catch(e)
{
}
}
else
{
process.send({cmd:"call", id:0, Name:Name, Params:Params});
}
};
setInterval(function ()
{
DApps.Accounts.Close();
DApps.Smart.DBSmart.Close();
global.BlockDB.CloseDBFile("block-header");
global.BlockDB.CloseDBFile("block-body");
}, 500);
setInterval(function ()
{
var MaxNumBlockDB = SERVER.GetMaxNumBlockDB();
var arr = SERVER.GetStatBlockchain("POWER_BLOCKCHAIN", 100);
if(arr.length)
{
var SumPow = 0;
var Count = 0;
for(var i = arr.length - 100; i < arr.length; i++)
if(arr[i])
{
SumPow += arr[i];
Count++;
}
var AvgPow = SumPow / Count;
var HashRate = Math.pow(2, AvgPow) / 1024 / 1024 / 1024;
ADD_TO_STAT("MAX:HASH_RATE_G", HashRate);
}
var Count = COUNT_BLOCK_PROOF + 16 - 1;
if(MaxNumBlockDB > Count)
{
var StartNum = MaxNumBlockDB - Count;
var BufWrite = SERVER.BlockChainToBuf(StartNum, StartNum, MaxNumBlockDB);
NodeBlockChain = BufWrite;
}
}, 1000);