update code
This commit is contained in:
412
Source/process/api-exchange.js
Normal file
412
Source/process/api-exchange.js
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
const crypto = require('crypto');
|
||||
WebApi2.GenerateKeys = function (Params)
|
||||
{
|
||||
var KeyPair = crypto.createECDH('secp256k1');
|
||||
var PrivKey = sha3(crypto.randomBytes(32));
|
||||
KeyPair.setPrivateKey(Buffer.from(PrivKey));
|
||||
var PubKey = KeyPair.getPublicKey('', 'compressed');
|
||||
return {result:1, PrivKey:GetHexFromArr(PrivKey), PubKey:GetHexFromArr(PubKey), Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
WebApi2.CreateAccount = function (Params,response)
|
||||
{
|
||||
if(typeof Params === "object" && Params.Name && Params.PrivKey)
|
||||
{
|
||||
var KeyPair = crypto.createECDH('secp256k1');
|
||||
KeyPair.setPrivateKey(Buffer.from(GetArrFromHex(Params.PrivKey)));
|
||||
var PubKey = KeyPair.getPublicKey('', 'compressed');
|
||||
var TR = {Type:TYPE_TRANSACTION_CREATE, Currency:Params.Currency, PubKey:PubKey, Name:Params.Name, Smart:Params.Smart, };
|
||||
var Body = BufLib.GetBufferFromObject(TR, FORMAT_CREATE, 1000, {}, 1);
|
||||
Body = Body.slice(0, Body.len + 12);
|
||||
SendTransaction(Body, TR, Params.Wait, function (result,text)
|
||||
{
|
||||
var Result = {result:result, text:text, TxID:GetHexFromArr(TR._TxID.slice(0, TR_TICKET_HASH_LENGTH + 6)), BlockNum:TR._BlockNum,
|
||||
Meta:Params.Meta, };
|
||||
var Str = JSON.stringify(Result);
|
||||
response.end(Str);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
var MapSendID = {};
|
||||
WebApi2.Send = function (Params,response,A,bJsonRet)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
var Coin;
|
||||
if(typeof Params.Amount === "number")
|
||||
Coin = COIN_FROM_FLOAT(Params.Amount);
|
||||
else
|
||||
Coin = Params.Amount;
|
||||
var FromNum = ParseNum(Params.FromID);
|
||||
if(!Coin)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Amount required"};
|
||||
if(!FromNum)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.FromID required"};
|
||||
if(!Params.ToID)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.ToID required"};
|
||||
var ToPubKeyArr = [];
|
||||
var ToID = 0;
|
||||
if(typeof Params.ToID === "string" && Params.ToID.length === 66)
|
||||
ToPubKeyArr = GetArrFromHex(Params.ToID);
|
||||
else
|
||||
ToID = ParseNum(Params.ToID);
|
||||
var DataFrom = DApps.Accounts.ReadState(FromNum);
|
||||
if(!DataFrom)
|
||||
return {result:0, Meta:Params.Meta, text:"Error read account: " + FromNum};
|
||||
var OperationID;
|
||||
if(!MapSendID[FromNum])
|
||||
{
|
||||
OperationID = DataFrom.Value.OperationID + 10;
|
||||
MapSendID[FromNum] = {};
|
||||
}
|
||||
else
|
||||
{
|
||||
OperationID = MapSendID[FromNum].OperationID;
|
||||
if((new Date() - MapSendID[FromNum].Date) > 8 * 1000)
|
||||
{
|
||||
OperationID += 20;
|
||||
}
|
||||
}
|
||||
OperationID++;
|
||||
MapSendID[FromNum].OperationID = OperationID;
|
||||
MapSendID[FromNum].Date = Date.now();
|
||||
var TR = {Type:111, Version:3, Reserve:0, FromID:FromNum, OperationID:OperationID, To:[{PubKey:ToPubKeyArr, ID:ToID, SumCOIN:Coin.SumCOIN,
|
||||
SumCENT:Coin.SumCENT}], Description:Params.Description, Body:[], };
|
||||
if(bJsonRet)
|
||||
return {result:1, Tx:TR};
|
||||
if(!Params.FromPrivKey)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.FromPrivKey required"};
|
||||
TR.Sign = DApps.Accounts.GetSignTransferTx(TR, GetArrFromHex(Params.FromPrivKey));
|
||||
var Body = BufLib.GetBufferFromObject(TR, FORMAT_MONEY_TRANSFER3, MAX_TRANSACTION_SIZE, {}, 1);
|
||||
Body = Body.slice(0, Body.len + 12);
|
||||
SendTransaction(Body, TR, Params.Wait, function (result,text)
|
||||
{
|
||||
var Result = {result:result, text:text, TxID:GetHexFromArr(TR._TxID.slice(0, TR_TICKET_HASH_LENGTH + 6)), BlockNum:TR._BlockNum,
|
||||
Meta:Params.Meta, };
|
||||
var Str = JSON.stringify(Result);
|
||||
response.end(Str);
|
||||
});
|
||||
return null;
|
||||
};
|
||||
WebApi2.GetBalance = function (Params,response)
|
||||
{
|
||||
if(typeof Params === "object")
|
||||
{
|
||||
var arr = DApps.Accounts.GetRowsAccounts(ParseNum(Params.AccountID), 1);
|
||||
if(arr.length)
|
||||
{
|
||||
var Account = arr[0];
|
||||
var Value = Account.Value;
|
||||
var Result = {result:1, SumCOIN:Value.SumCOIN, SumCENT:Value.SumCENT, Currency:Account.Currency, PubKey:GetHexFromArr(Account.PubKey),
|
||||
Meta:Params.Meta, };
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
WebApi2.GetTransaction = function (Params)
|
||||
{
|
||||
if(typeof Params === "object" && Params.TxID)
|
||||
{
|
||||
var Arr = GetArrFromHex(Params.TxID);
|
||||
var BlockNum = ReadUintFromArr(Arr, TR_TICKET_HASH_LENGTH);
|
||||
var Block = SERVER.ReadBlockDB(BlockNum);
|
||||
if(Block && Block.arrContent)
|
||||
{
|
||||
for(var i = 0; i < Block.arrContent.length; i++)
|
||||
{
|
||||
var Body = Block.arrContent[i];
|
||||
var Arr2 = GetTxID(BlockNum, Body);
|
||||
if(CompareArr(Arr2, Arr) === 0)
|
||||
{
|
||||
return GetTransactionFromBody(Params, Block, i, Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(typeof Params === "object" && Params.BlockNum && Params.TrNum !== undefined)
|
||||
{
|
||||
var Block = SERVER.ReadBlockDB(Params.BlockNum);
|
||||
if(Block && Block.arrContent)
|
||||
{
|
||||
var Body = Block.arrContent[Params.TrNum];
|
||||
if(Body)
|
||||
{
|
||||
return GetTransactionFromBody(Params, Block, Params.TrNum, Body);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
WebApi2.GetHistoryTransactions = function (Params)
|
||||
{
|
||||
if(typeof Params === "object" && Params.AccountID)
|
||||
{
|
||||
if(!Params.Count)
|
||||
Params.Count = 100;
|
||||
if(Params.Confirm === undefined)
|
||||
Params.Confirm = 8;
|
||||
var arr = DApps.Accounts.GetHistory(Params.AccountID, Params.Count, Params.NextPos, Params.Confirm);
|
||||
if(Params.GetTxID || Params.GetDescription)
|
||||
{
|
||||
for(var i = 0; i < arr.length; i++)
|
||||
{
|
||||
var Item = arr[i];
|
||||
var Block = SERVER.ReadBlockDB(Item.BlockNum);
|
||||
if(!Block || (!Block.arrContent))
|
||||
continue;
|
||||
var Body = Block.arrContent[Item.TrNum];
|
||||
if(!Body)
|
||||
continue;
|
||||
if(Params.GetTxID)
|
||||
{
|
||||
Item.TxID = GetHexFromArr(GetTxID(Item.BlockNum, Body));
|
||||
}
|
||||
if(Params.GetDescription)
|
||||
{
|
||||
var TR = DApps.Accounts.GetObjectTransaction(Body);
|
||||
if(TR)
|
||||
{
|
||||
Item.Description = TR.Description;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var Result = {result:arr.length > 0 ? 1 : 0, History:arr, Tail:DApps.Accounts.DBStateHistory.Read(Params.AccountID), Meta:Params ? Params.Meta : undefined};
|
||||
return Result;
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
WebApi2.CreateRawTransaction = function (Params)
|
||||
{
|
||||
if(typeof Params === "object")
|
||||
{
|
||||
var Ret = WebApi2.Send(Params, undefined, undefined, 1);
|
||||
TxArrToHex(Ret.Tx);
|
||||
Ret.Meta = Params.Meta;
|
||||
return Ret;
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
WebApi2.SignRawTransaction = function (Params)
|
||||
{
|
||||
if(typeof Params === "object" && Params.Tx)
|
||||
{
|
||||
if(!Params.FromPrivKey)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.FromPrivKey required"};
|
||||
if(typeof Params.Tx !== "object")
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Tx required"};
|
||||
if(!Params.Tx.To || !Params.Tx.To.length)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Tx.To required"};
|
||||
var TR = Params.Tx;
|
||||
TxHexToArr(TR);
|
||||
TR.Sign = DApps.Accounts.GetSignTransferTx(TR, GetArrFromHex(Params.FromPrivKey));
|
||||
TxArrToHex(TR);
|
||||
var Ret = {result:1, Tx:TR, Meta:Params ? Params.Meta : undefined};
|
||||
return Ret;
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
WebApi2.SendRawTransaction = function (Params,response)
|
||||
{
|
||||
if(typeof Params === "object" && Params.Tx)
|
||||
{
|
||||
if(typeof Params.Tx !== "object")
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Tx required"};
|
||||
if(!Params.Tx.To || !Params.Tx.To.length)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Tx.To required"};
|
||||
if(!Params.Tx.Sign)
|
||||
return {result:0, Meta:Params.Meta, text:"Params.Tx.Sign required"};
|
||||
var TR = Params.Tx;
|
||||
TxHexToArr(TR);
|
||||
var Body = BufLib.GetBufferFromObject(TR, FORMAT_MONEY_TRANSFER3, MAX_TRANSACTION_SIZE, {}, 1);
|
||||
Body = Body.slice(0, Body.len + 12);
|
||||
SendTransaction(Body, TR, Params.Wait, function (result,text)
|
||||
{
|
||||
var Result = {result:result, text:text, TxID:GetHexFromArr(TR._TxID.slice(0, TR_TICKET_HASH_LENGTH + 6)), BlockNum:TR._BlockNum,
|
||||
Meta:Params.Meta, };
|
||||
var Str = JSON.stringify(Result);
|
||||
response.end(Str);
|
||||
});
|
||||
return null;
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
|
||||
function TxArrToHex(TR)
|
||||
{
|
||||
if(TR && TR.To && TR.To[0].PubKey)
|
||||
{
|
||||
if(TR.To[0].PubKey.length)
|
||||
TR.To[0].PubKey = GetHexFromArr(TR.To[0].PubKey);
|
||||
else
|
||||
TR.To[0].PubKey = "";
|
||||
if(TR.Sign && TR.Sign.length)
|
||||
TR.Sign = GetHexFromArr(TR.Sign);
|
||||
else
|
||||
TR.Sign = "";
|
||||
TR.Body = undefined;
|
||||
TR.Reserve = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
function TxHexToArr(TR)
|
||||
{
|
||||
TR.Body = [];
|
||||
if(TR.Sign && TR.Sign.length)
|
||||
TR.Sign = GetArrFromHex(TR.Sign);
|
||||
else
|
||||
TR.Sign = [];
|
||||
for(var i = 0; i < TR.To.length; i++)
|
||||
{
|
||||
TR.To[i].PubKey = GetArrFromHex(TR.To[i].PubKey);
|
||||
}
|
||||
};
|
||||
var DELTA_FOR_TIME_TX = 1;
|
||||
|
||||
function GetTxID(BlockNum,Body)
|
||||
{
|
||||
var Nonce = ReadUintFromArr(Body, Body.length - 6);
|
||||
var Arr2 = CreateTxID(Body, BlockNum, Nonce);
|
||||
return Arr2.slice(0, TR_TICKET_HASH_LENGTH + 6);
|
||||
};
|
||||
|
||||
function CreateTxID(body,BlockNum,Nonce)
|
||||
{
|
||||
body.writeUIntLE(BlockNum, body.length - 12, 6);
|
||||
body.writeUIntLE(Nonce, body.length - 6, 6);
|
||||
var HASH = sha3(body);
|
||||
var FullHashTicket = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
for(var i = 0; i < TR_TICKET_HASH_LENGTH; i++)
|
||||
FullHashTicket[i] = HASH[i];
|
||||
WriteUintToArrOnPos(FullHashTicket, BlockNum, TR_TICKET_HASH_LENGTH);
|
||||
return FullHashTicket;
|
||||
};
|
||||
|
||||
function GetBlockNumTr(arr)
|
||||
{
|
||||
var BlockNum = DELTA_FOR_TIME_TX + GetCurrentBlockNumByTime();
|
||||
if(arr[0] === TYPE_TRANSACTION_CREATE)
|
||||
{
|
||||
var BlockNum2 = Math.floor(BlockNum / 10) * 10;
|
||||
if(BlockNum2 < BlockNum)
|
||||
BlockNum2 = BlockNum2 + 10;
|
||||
BlockNum = BlockNum2;
|
||||
}
|
||||
return BlockNum;
|
||||
};
|
||||
|
||||
function CreateHashBodyPOWInnerMinPower(TR,arr,MinPow,startnonce)
|
||||
{
|
||||
var BlockNum = GetBlockNumTr(arr);
|
||||
if(MinPow === undefined)
|
||||
{
|
||||
MinPow = MIN_POWER_POW_TR + Math.log2(arr.length / 128);
|
||||
}
|
||||
var nonce = startnonce;
|
||||
while(1)
|
||||
{
|
||||
var TxID = CreateTxID(arr, BlockNum, nonce);
|
||||
var power = GetPowPower(sha3(TxID));
|
||||
if(power >= MinPow)
|
||||
{
|
||||
TR._TxID = TxID;
|
||||
TR._BlockNum = BlockNum;
|
||||
ToLog("Find: " + power + " for block:" + BlockNum);
|
||||
return nonce;
|
||||
}
|
||||
nonce++;
|
||||
if(nonce % 2000 === 0)
|
||||
{
|
||||
BlockNum = GetBlockNumTr(arr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function SendTransaction(Body,TR,Wait,F)
|
||||
{
|
||||
if(Body.length > 16000)
|
||||
{
|
||||
TR._result = 0;
|
||||
TR._text = "Error length transaction =" + Body.length + " (max size=16000)";
|
||||
F(1, TR, Body);
|
||||
return ;
|
||||
}
|
||||
global.GlobalRunID++;
|
||||
let WebID = global.GlobalRunID;
|
||||
CreateNonceAndSend(0, 0);
|
||||
|
||||
function CreateNonceAndSend(startnonce,NumNext)
|
||||
{
|
||||
if(!NumNext)
|
||||
NumNext = 0;
|
||||
if(NumNext > 10)
|
||||
{
|
||||
F(0, TR, Body);
|
||||
return ;
|
||||
}
|
||||
var nonce = CreateHashBodyPOWInnerMinPower(TR, Body, undefined, startnonce);
|
||||
process.RunRPC("AddTransactionFromWeb", {WebID:WebID, HexValue:GetHexFromArr(Body)}, function (Err,text)
|
||||
{
|
||||
TR._result = Err ? 0 : 1;
|
||||
TR._text = text;
|
||||
if(text === "Not add" || text === "Bad PoW")
|
||||
{
|
||||
CreateNonceAndSend(nonce + 1, NumNext + 1);
|
||||
return ;
|
||||
}
|
||||
else
|
||||
if(text === "Bad time")
|
||||
{
|
||||
if(DELTA_FOR_TIME_TX < 6)
|
||||
{
|
||||
DELTA_FOR_TIME_TX++;
|
||||
ToLog("New set Delta time: " + DELTA_FOR_TIME_TX);
|
||||
CreateNonceAndSend(0, NumNext + 1);
|
||||
return ;
|
||||
}
|
||||
}
|
||||
if(Wait && TR._result)
|
||||
{
|
||||
global.GlobalRunMap[WebID] = F;
|
||||
}
|
||||
else
|
||||
{
|
||||
F(TR._result < 1 ? 0 : 1, text);
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
function GetTransactionFromBody(Params,Block,TrNum,Body)
|
||||
{
|
||||
var TR = DApps.Accounts.GetObjectTransaction(Body);
|
||||
if(TR)
|
||||
{
|
||||
ConvertBufferToStr(TR);
|
||||
TR.result = 1;
|
||||
TR.Meta = Params.Meta;
|
||||
if(Block.VersionBody === 1 && Block.arrContentResult)
|
||||
{
|
||||
TR.result = Block.arrContentResult[TrNum];
|
||||
}
|
||||
TR.BlockNum = Block.BlockNum;
|
||||
TR.TrNum = TrNum;
|
||||
return TR;
|
||||
}
|
||||
return {result:0, Meta:Params ? Params.Meta : undefined};
|
||||
};
|
||||
10
Source/process/dogs.js
Normal file
10
Source/process/dogs.js
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
789
Source/process/main-process.js
Normal file
789
Source/process/main-process.js
Normal file
@@ -0,0 +1,789 @@
|
||||
/*
|
||||
* @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 = "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");
|
||||
const DEF_PERIOD_SIGN_LIB = 500;
|
||||
setTimeout(function ()
|
||||
{
|
||||
TestSignLib(DEF_PERIOD_SIGN_LIB);
|
||||
}, 4000);
|
||||
global.glCurNumFindArr = 0;
|
||||
global.ArrReconnect = [];
|
||||
global.ArrConnect = [];
|
||||
var FindList = [{"ip":"91.235.136.81", "port":30005}, {"ip":"149.154.70.158", "port":30000}, {"ip":"185.240.243.182", "port":30000},
|
||||
{"ip":"212.109.197.205", "port":30000}, {"ip":"212.109.197.209", "port":30000}, {"ip":"80.87.192.24", "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:10 * 1000};
|
||||
global.WEB_PROCESS = WebProcess;
|
||||
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) < NODES_DELTA_CALC_HOUR * 3600 * 1000)
|
||||
arr2.push({ip:Item.ip, port:Item.port, webport:Item.webport});
|
||||
else
|
||||
if(Item.LastTimeGetNode && (CurTime - Item.LastTimeGetNode) < NODES_DELTA_CALC_HOUR * 3600 * 1000)
|
||||
arr2.push({ip:Item.ip, port:Item.port, webport:Item.webport});
|
||||
}
|
||||
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(Params)
|
||||
{
|
||||
var body = GetArrFromHex(Params.HexValue);
|
||||
if(global.TX_PROCESS && global.TX_PROCESS.Worker)
|
||||
{
|
||||
var StrHex = GetHexFromArr(sha3(body));
|
||||
global.TX_PROCESS.Worker.send({cmd:"FindTX", TX:StrHex, Web:1, WebID:Params.WebID});
|
||||
}
|
||||
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:50000};
|
||||
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 Delta0 = Date.now() - ITEM.LastAlive;
|
||||
if(Delta0 >= 0)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ToLog("ERR KILL");
|
||||
}
|
||||
ITEM.Worker = undefined;
|
||||
}
|
||||
}
|
||||
if(!ITEM.Worker)
|
||||
{
|
||||
ITEM.LastAlive = (Date.now()) + ITEM.PeriodAlive * 3;
|
||||
ToLog("STARTING " + ITEM.Name);
|
||||
ITEM.Worker = Fork(ITEM.Path, ["READONLYDB"]);
|
||||
ITEM.pid = ITEM.Worker.pid;
|
||||
ToLog("STARTED " + ITEM.Name + ":" + ITEM.pid);
|
||||
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
|
||||
{
|
||||
if(typeof msg.Params === "object" && msg.Params.F)
|
||||
{
|
||||
global[msg.Name](msg.Params, function (Err,Ret)
|
||||
{
|
||||
if(msg.id && ITEM.Worker)
|
||||
ITEM.Worker.send({cmd:"retcall", id:msg.id, Err:Err, Params:Ret});
|
||||
});
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
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 "RetFindTX":
|
||||
if(WebProcess && WebProcess.Worker)
|
||||
{
|
||||
WebProcess.Worker.send(msg);
|
||||
if(msg.Web)
|
||||
break;
|
||||
}
|
||||
ToLogClient(msg.ResultStr, msg.TX, msg.bFinal);
|
||||
break;
|
||||
case "online":
|
||||
if(ITEM.Worker)
|
||||
ToLog("RUNNING " + ITEM.Name + " : " + msg.message + " pid: " + ITEM.Worker.pid);
|
||||
break;
|
||||
case "WriteBodyResult":
|
||||
var Block = SERVER.ReadBlockDB(msg.BlockNum);
|
||||
if(Block)
|
||||
{
|
||||
Block.arrContentResult = msg.arrContentResult;
|
||||
SERVER.WriteBodyResultDB(Block);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(ITEM.OnMessage)
|
||||
{
|
||||
ITEM.OnMessage(msg);
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
ITEM.Worker.on('error', function (err)
|
||||
{
|
||||
});
|
||||
ITEM.Worker.on('close', function (code)
|
||||
{
|
||||
ToError("CLOSE " + ITEM.Name);
|
||||
});
|
||||
}
|
||||
}
|
||||
if(ITEM.Worker)
|
||||
{
|
||||
ITEM.Worker.send({cmd:"Alive"});
|
||||
}
|
||||
}, 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 each 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("RUNNING 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,
|
||||
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);
|
||||
require("../core/update");
|
||||
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);
|
||||
}
|
||||
};
|
||||
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;
|
||||
};
|
||||
global.SpeedSignLib = 0;
|
||||
global.TestSignLib = TestSignLib;
|
||||
|
||||
function TestSignLib(MaxTime)
|
||||
{
|
||||
if(!MaxTime)
|
||||
MaxTime = DEF_PERIOD_SIGN_LIB;
|
||||
var hash = Buffer.from(GetArrFromHex("A6B0914953F515F4686B2BA921B8FAC66EE6A6D3E317B43E981EBBA52393BFC6"));
|
||||
var PubKey = Buffer.from(GetArrFromHex("026A04AB98D9E4774AD806E302DDDEB63BEA16B5CB5F223EE77478E861BB583EB3"));
|
||||
var Sign = Buffer.from(GetArrFromHex("5D5382C65E4C1E8D412D5F30F87B8F72F371E9E4FC170761BCE583A961CF44966F92B38D402BC1CBCB7567335051A321B93F4E32112129AED4AB602E093A1187"));
|
||||
var startTime = process.hrtime();
|
||||
var deltaTime = 1;
|
||||
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);
|
||||
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, see detail: https://www.npmjs.com/package/secp256k1");
|
||||
global.SpeedSignLib = Num;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
global.SpeedSignLib = Math.floor(Num * MaxTime / deltaTime);
|
||||
ToLog("TestSignLib: " + global.SpeedSignLib + " per sec");
|
||||
return 1;
|
||||
};
|
||||
97
Source/process/pow-process.js
Normal file
97
Source/process/pow-process.js
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* @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 = "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}), 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
425
Source/process/static-process.js
Normal file
425
Source/process/static-process.js
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* @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";
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
require("../core/constant");
|
||||
require('../core/block-loader-const');
|
||||
require('../core/rest_tables.js');
|
||||
require('../system/accounts.js');
|
||||
require('../system/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 "GETBLOCKHEADER100":
|
||||
GETBLOCKHEADER100(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.Close();
|
||||
DApps.Accounts.Close();
|
||||
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;
|
||||
var Hash100;
|
||||
var Count = Data.Count;
|
||||
if(!Count || Count < 0 || !EndNum100)
|
||||
return ;
|
||||
if(Count > COUNT_BLOCKS_FOR_LOAD)
|
||||
Count = COUNT_BLOCKS_FOR_LOAD;
|
||||
var Arr = [];
|
||||
var Data100 = SERVER.DBHeader100.Read(EndNum100);
|
||||
if(Data100 && CompareArr(Data100.Hash100, LoadHash100) === 0)
|
||||
{
|
||||
var StartNum = EndNum100 - Count + 1;
|
||||
if(StartNum < 0)
|
||||
StartNum = 0;
|
||||
for(var Num = StartNum; Num <= EndNum100; Num++)
|
||||
{
|
||||
Data100 = SERVER.DBHeader100.Read(Num);
|
||||
if(Num === StartNum)
|
||||
Arr.push(Data100.Hash100);
|
||||
Arr.push(Data100.Hash);
|
||||
}
|
||||
}
|
||||
var BufWrite = BufLib.GetBufferFromObject(Arr, "[hash]", MAX_PACKET_LENGTH, {});
|
||||
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 = 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";
|
||||
}
|
||||
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 ;
|
||||
if(IsZeroArr(Data.AccHash))
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 StartAccount = Data.AccNum;
|
||||
var EndAccount = StartAccount + LengthAccount - 1;
|
||||
if(EndAccount > Max)
|
||||
EndAccount = Max;
|
||||
var Tree = GetRestMerkleTree(BlockNumRest, RestIndexArr);
|
||||
if(CompareArr(Data.AccHash, Tree.Root) !== 0)
|
||||
{
|
||||
ToLog("Get bad rest acc hash: " + BlockNumRest + " = " + GetHexFromArr(Data.AccHash) + "/" + GetHexFromArr(Tree.Root), 2);
|
||||
ArrRest = [];
|
||||
nResult = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ArrRest = GetArrRest(BlockNumRest, StartAccount, EndAccount);
|
||||
ProofHash = Tree.Root;
|
||||
var RetProof = GetMerkleProof(Tree.LevelsHash, StartAccount, EndAccount);
|
||||
ProofArrL = RetProof.ArrL;
|
||||
ProofArrR = RetProof.ArrR;
|
||||
BufLength = 1000 + ArrRest.length * WorkFormatLength;
|
||||
BufLength += ProofArrL.length * 32 + ProofArrR.length * 32 + 32;
|
||||
}
|
||||
}
|
||||
var Data2 = {Result:nResult, Arr:ArrRest, Version:1, ProofHash:ProofHash, ProofArrL:ProofArrL, ProofArrR:ProofArrR};
|
||||
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});
|
||||
};
|
||||
var glMapForHash = {};
|
||||
|
||||
function GetArrRest(BlockNumRest,StartAccount,EndAccount,bHashOnly)
|
||||
{
|
||||
var ArrRest = [];
|
||||
var WorkStruct = {};
|
||||
var WorkFormat = DApps.Accounts.FORMAT_ACCOUNT_ROW;
|
||||
var WorkFormatLength = DApps.Accounts.SIZE_ACCOUNT_ROW;
|
||||
for(var Num = StartAccount; Num <= EndAccount; Num++)
|
||||
{
|
||||
var FindItem = undefined;
|
||||
var RestData = 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 = 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 = BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
|
||||
Hash = shaarr(Buf);
|
||||
glMapForHash[key] = Hash;
|
||||
}
|
||||
ArrRest.push(Hash);
|
||||
}
|
||||
else
|
||||
{
|
||||
var Buf = BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
|
||||
ArrRest.push(Buf);
|
||||
}
|
||||
}
|
||||
return ArrRest;
|
||||
};
|
||||
var glMapRest = {};
|
||||
|
||||
function GetRestMerkleTree(BlockNumRest,RestIndexArr)
|
||||
{
|
||||
var MerkleTree = glMapRest[BlockNumRest];
|
||||
if(!MerkleTree)
|
||||
{
|
||||
ToLog("Create new glMapRest key: " + BlockNumRest, 2);
|
||||
var startTime = process.hrtime();
|
||||
var EndAccount = 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;
|
||||
}
|
||||
UpdateMerklTree(MerkleTree, MerkleCalc, 0);
|
||||
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;
|
||||
ToLog("Create delta time: " + deltaTime1 + "/" + deltaTime2 + " s Tree.Root=" + 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])
|
||||
{
|
||||
ToLog("Delete old glMapRest key: " + key, 2);
|
||||
delete glMapRest[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return MerkleTree;
|
||||
};
|
||||
411
Source/process/tx-process.js
Normal file
411
Source/process/tx-process.js
Normal file
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* @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";
|
||||
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(PrepareStatEverySecond, 1000);
|
||||
if(process.send)
|
||||
{
|
||||
setInterval(function ()
|
||||
{
|
||||
process.send({cmd:"Alive"});
|
||||
}, 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);
|
||||
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)
|
||||
{
|
||||
ToLog("TX-PROCESS: ALIVE TIMEOUT Stop and exit: " + Delta);
|
||||
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.Close();
|
||||
}
|
||||
DoTXProcess();
|
||||
}, 10);
|
||||
var BlockTree = new STreeBuffer(30 * 1000, 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(bShowDetail)
|
||||
ToLog("!BlockMin");
|
||||
return ;
|
||||
}
|
||||
var StartTime = Date.now();
|
||||
if(bShowDetail)
|
||||
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 = SERVER.ReadBlockDB(Num);
|
||||
if(!Block)
|
||||
{
|
||||
if(bShowDetail)
|
||||
ToLog("!Block");
|
||||
break;
|
||||
}
|
||||
if(!IsValidSumHash(Block))
|
||||
{
|
||||
break;
|
||||
}
|
||||
var Item = BlockTree.LoadValue(Block.BlockNum, 1);
|
||||
if(Item && CompareArr(Item.SumHash, Block.SumHash) === 0)
|
||||
{
|
||||
if(bShowDetail)
|
||||
ToLog("WAS CALC: " + Num + " SumHash: " + GetHexFromArr(Block.SumHash).substr(0, 12));
|
||||
continue;
|
||||
}
|
||||
if(Num > 0)
|
||||
{
|
||||
var Block0 = SERVER.ReadBlockDB(Num - 1);
|
||||
if(Block0)
|
||||
{
|
||||
var Item0 = BlockTree.LoadValue(Block0.BlockNum, 1);
|
||||
if(Item0 && CompareArr(Item0.SumHash, Block0.SumHash) !== 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
if(bShowDetail)
|
||||
ToLog("MaxNumBlockDB<LastBlockNum: " + MaxNumBlockDB + "<" + LastBlockNum);
|
||||
LastBlockNum = MaxNumBlockDB - 1;
|
||||
BlockTree.Clear();
|
||||
}
|
||||
if(LastBlockNum < MinimalValidBlock)
|
||||
LastBlockNum = MinimalValidBlock;
|
||||
if(bShowDetail)
|
||||
ToLog("FindMinimal from LastBlockNum=" + LastBlockNum);
|
||||
for(var Num = LastBlockNum; Num--; Num >= 0)
|
||||
{
|
||||
if(Num < MinimalValidBlock)
|
||||
break;
|
||||
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;
|
||||
if(bShowDetail)
|
||||
ToLog("" + Num + " " + Block.BlockNum + ". Item=" + JSON.stringify(Item) + " MinimalValidBlock=" + MinimalValidBlock);
|
||||
}
|
||||
if(bShowDetail)
|
||||
ToLog("MinimalValidBlock:" + MinimalValidBlock);
|
||||
if(MinimalValidBlock === 0 && LastBlockNum > 0)
|
||||
{
|
||||
RewriteAllTransactions();
|
||||
}
|
||||
Block = SERVER.ReadBlockHeaderDB(MinimalValidBlock);
|
||||
return Block;
|
||||
};
|
||||
|
||||
function IsValidSumHash(Block)
|
||||
{
|
||||
if(Block.BlockNum <= MinimalValidBlock + BLOCK_PROCESSING_LENGTH2)
|
||||
return 1;
|
||||
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, 2);
|
||||
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum, BlockNumMin:MinimalValidBlock});
|
||||
}
|
||||
StateTX = DApps.Accounts.DBStateTX.Read(0);
|
||||
LastBlockNum = StateTX.BlockNum;
|
||||
MinimalValidBlock = StateTX.BlockNumMin;
|
||||
LastBlockNum = PERIOD_ACCOUNT_HASH * Math.trunc(LastBlockNum / PERIOD_ACCOUNT_HASH);
|
||||
if(LastBlockNum > 100)
|
||||
{
|
||||
LastBlockNum = 1 + LastBlockNum - 100;
|
||||
}
|
||||
ToLog("Start CalcMerkleTree", 2);
|
||||
DApps.Accounts.CalcMerkleTree(1);
|
||||
ToLog("Finsih CalcMerkleTree", 2);
|
||||
if(LastBlockNum <= 0)
|
||||
RewriteAllTransactions();
|
||||
else
|
||||
ToLog("Start NUM = " + LastBlockNum, 2);
|
||||
};
|
||||
global.ClearDataBase = ClearDataBase;
|
||||
|
||||
function ClearDataBase()
|
||||
{
|
||||
MinimalValidBlock = 0;
|
||||
for(var key in DApps)
|
||||
{
|
||||
DApps[key].ClearDataBase();
|
||||
}
|
||||
LastBlockNum = 0;
|
||||
BlockTree.Clear();
|
||||
};
|
||||
global.RewriteAllTransactions = RewriteAllTransactions;
|
||||
|
||||
function RewriteAllTransactions()
|
||||
{
|
||||
if(MinimalValidBlock > 0)
|
||||
{
|
||||
ToLog("*************Cant run RewriteAllTransactions, MinimalValidBlock:" + MinimalValidBlock, 2);
|
||||
return ;
|
||||
}
|
||||
ToLog("*************RewriteAllTransactions");
|
||||
for(var key in DApps)
|
||||
{
|
||||
DApps[key].ClearDataBase();
|
||||
}
|
||||
LastBlockNum = 0;
|
||||
BlockTree.Clear();
|
||||
ToLog("Start num = " + LastBlockNum, 2);
|
||||
};
|
||||
global.ReWriteDAppTransactions = ReWriteDAppTransactions;
|
||||
|
||||
function ReWriteDAppTransactions(Params)
|
||||
{
|
||||
var StartNum = Params.StartNum;
|
||||
var EndNum = Params.EndNum;
|
||||
ToLog("ReWriteDAppTransactions: " + StartNum + " - " + EndNum);
|
||||
BlockTree.Clear();
|
||||
if(StartNum < LastBlockNum)
|
||||
LastBlockNum = StartNum;
|
||||
ToLog("Start num = " + LastBlockNum, 2);
|
||||
};
|
||||
|
||||
function TXPrepareLoadRest(BlockNum)
|
||||
{
|
||||
StopTxProcess = 1;
|
||||
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()
|
||||
{
|
||||
StopTxProcess = 0;
|
||||
ToLog("Start TXWriteAccHash: " + MinimalValidBlock, 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);
|
||||
}
|
||||
DApps.Accounts.CalcMerkleTree(1);
|
||||
var Block = {BlockNum:MinimalValidBlock, SumHash:[]};
|
||||
var MaxAccount = DApps.Accounts.GetMaxAccount();
|
||||
var DataHash = DApps.Accounts.CalcHash(Block, MaxAccount);
|
||||
return DataHash;
|
||||
};
|
||||
global.TXWriteAccHash = TXWriteAccHash;
|
||||
global.EvalCode = function (Code)
|
||||
{
|
||||
var Result;
|
||||
try
|
||||
{
|
||||
var ret = eval(Code);
|
||||
Result = JSON.stringify(ret, "", 4);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
Result = "" + e;
|
||||
}
|
||||
return Result;
|
||||
};
|
||||
984
Source/process/web-process.js
Normal file
984
Source/process/web-process.js
Normal file
@@ -0,0 +1,984 @@
|
||||
/*
|
||||
* @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 = "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 = 600;
|
||||
require("../core/constant");
|
||||
global.MAX_STAT_PERIOD = 600;
|
||||
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 = 600;
|
||||
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":
|
||||
Exit();
|
||||
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;
|
||||
}
|
||||
case "RetFindTX":
|
||||
{
|
||||
if(msg.WebID)
|
||||
{
|
||||
var F = global.GlobalRunMap[msg.WebID];
|
||||
if(F)
|
||||
{
|
||||
delete global.GlobalRunMap[msg.WebID];
|
||||
F(msg.Result, msg.ResultStr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ArrLogClient.push({text:msg.ResultStr, key:msg.TX, final:msg.bFinal, });
|
||||
break;
|
||||
}
|
||||
case "Eval":
|
||||
EvalCode(msg.Code);
|
||||
break;
|
||||
}
|
||||
});
|
||||
var RedirectServer;
|
||||
var HostingServer;
|
||||
|
||||
function Exit()
|
||||
{
|
||||
ToLogWeb("=Exit1=");
|
||||
if(RedirectServer)
|
||||
RedirectServer.close();
|
||||
if(HostingServer)
|
||||
HostingServer.close();
|
||||
ToLogWeb("=Exit2=");
|
||||
process.exit(0);
|
||||
};
|
||||
|
||||
function CheckAlive()
|
||||
{
|
||||
if(global.NOALIVE)
|
||||
return ;
|
||||
var Delta = Date.now() - LastAlive;
|
||||
if(Delta > CHECK_STOP_CHILD_PROCESS)
|
||||
{
|
||||
Exit();
|
||||
return ;
|
||||
}
|
||||
};
|
||||
process.on('uncaughtException', function (err)
|
||||
{
|
||||
ToError(err.stack);
|
||||
ToLog(err.stack);
|
||||
TO_ERROR_LOG("HOSTING", 777, err);
|
||||
ToLog("-----------------HOSTING EXIT------------------", 0);
|
||||
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 IndexName = "index.html";
|
||||
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')();
|
||||
RedirectServer = require('http').createServer(greenlock.middleware(redir));
|
||||
RedirectServer.on('error', function (err)
|
||||
{
|
||||
ToError('RedirectServer: ' + err.code);
|
||||
});
|
||||
RedirectServer.listen(80);
|
||||
var GetNewSert = 1;
|
||||
if(fs.existsSync(file_sert))
|
||||
{
|
||||
var certs = LoadParams(file_sert, {});
|
||||
var Delta = certs.expiresAt - Date.now();
|
||||
if(Delta >= 10 * 24 * 3600 * 1000)
|
||||
{
|
||||
ToLog("USE EXIST 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", 0);
|
||||
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.headers)
|
||||
return ;
|
||||
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);
|
||||
ToLogWeb("Get Path:" + Path);
|
||||
ADD_TO_STAT("HTTP_ALL");
|
||||
if(global.STAT_MODE === 2)
|
||||
response.DetailStatName = ":" + Path;
|
||||
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, 0);
|
||||
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;
|
||||
var TimeToRerun = 3000;
|
||||
|
||||
function RunListenServer()
|
||||
{
|
||||
HostingServer.on('error', function (err)
|
||||
{
|
||||
if(err.code === 'EADDRINUSE')
|
||||
{
|
||||
TimeToRerun = Math.floor(TimeToRerun * 1.1);
|
||||
if(TimeToRerun > 1000000 * 1000)
|
||||
return ;
|
||||
ToLogClient('Port ' + global.HTTP_HOSTING_PORT + ' in use, retrying...');
|
||||
if(HostingServer.Server)
|
||||
HostingServer.Server.close();
|
||||
if(!bWasRun)
|
||||
setTimeout(function ()
|
||||
{
|
||||
RunListenServer();
|
||||
}, TimeToRerun);
|
||||
return ;
|
||||
}
|
||||
ToError("H##6");
|
||||
ToError(err);
|
||||
});
|
||||
ToLogClient("Prepare to run WEB-server on port: " + global.HTTP_HOSTING_PORT);
|
||||
HostingServer.listen(global.HTTP_HOSTING_PORT, LISTEN_IP, function ()
|
||||
{
|
||||
if(!bWasRun)
|
||||
ToLogClient("Run WEB-server on " + LISTEN_IP + ":" + global.HTTP_HOSTING_PORT);
|
||||
bWasRun = 1;
|
||||
});
|
||||
};
|
||||
var SiteFolder = GetNormalPathString("./SITE");
|
||||
if(!fs.existsSync(SiteFolder))
|
||||
{
|
||||
IndexName = "web-wallet.html";
|
||||
}
|
||||
var LangPathMap = {};
|
||||
LangPathMap["ru"] = 1;
|
||||
LangPathMap["cn"] = 1;
|
||||
LangPathMap["de"] = 1;
|
||||
LangPathMap["blog"] = 1;
|
||||
LangPathMap["docs"] = 1;
|
||||
LangPathMap["game"] = 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["history.html"] = 1;
|
||||
WalletFileMap["blockviewer.html"] = 1;
|
||||
WalletFileMap["web-wallet.html"] = 1;
|
||||
WalletFileMap["address_book.png"] = 1;
|
||||
WalletFileMap["mobile-wallet.html"] = 1;
|
||||
WalletFileMap["mobile-wallet.js"] = 1;
|
||||
WalletFileMap["mobile-wallet.css"] = 1;
|
||||
WalletFileMap["reload.svg"] = 1;
|
||||
WalletFileMap["T.svg"] = 1;
|
||||
WalletFileMap["B.svg"] = 1;
|
||||
WalletFileMap["blank.svg"] = 1;
|
||||
WalletFileMap["info.svg"] = 1;
|
||||
WalletFileMap["info.svg"] = 1;
|
||||
WalletFileMap["check.svg"] = 1;
|
||||
WalletFileMap["right-arrow.svg"] = 1;
|
||||
WalletFileMap["down-arrow.svg"] = 1;
|
||||
WalletFileMap["glass.svg"] = 1;
|
||||
WalletFileMap["dapp-edit.html"] = 1;
|
||||
WalletFileMap["TeraLogo.svg"] = 1;
|
||||
WalletFileMap["mobile-wallet.html"] = "web-wallet.html";
|
||||
global.WebApi2 = {};
|
||||
global.HostingCaller = {};
|
||||
|
||||
function DoCommandNew(response,Type,Path,Params)
|
||||
{
|
||||
if(Path.substring(0, 1) === "/")
|
||||
Path = Path.substring(1);
|
||||
var ArrPath = Path.split('/', 5);
|
||||
var Caller = HostingCaller;
|
||||
var Method = ArrPath[0];
|
||||
var APIv2 = 0;
|
||||
if(ArrPath[0] === "api")
|
||||
{
|
||||
if(ArrPath[1] === "v2")
|
||||
{
|
||||
APIv2 = 1;
|
||||
if(!global.USE_HARD_API_V2)
|
||||
{
|
||||
response.writeHead(200, {'Content-Type':'text/plain', 'Access-Control-Allow-Origin':"*"});
|
||||
response.end(JSON.stringify({result:0, text:"You must set const USE_HARD_API_V2:1"}));
|
||||
return ;
|
||||
}
|
||||
Caller = WebApi2;
|
||||
}
|
||||
Method = ArrPath[2];
|
||||
}
|
||||
ADD_TO_STAT("HTTP:" + Method);
|
||||
if(global.STAT_MODE === 2)
|
||||
response.DetailStatName = ":" + Method;
|
||||
var F = Caller[Method];
|
||||
if(F)
|
||||
{
|
||||
response.writeHead(200, {'Content-Type':'text/plain', 'Access-Control-Allow-Origin':"*"});
|
||||
if(!global.USE_API_V1 && !APIv2)
|
||||
{
|
||||
response.end(JSON.stringify({result:0, text:"This node not use USE_API_V1"}));
|
||||
return ;
|
||||
}
|
||||
var Ret;
|
||||
try
|
||||
{
|
||||
Ret = F(Params, response, ArrPath);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
Ret = {result:0, text:e.message, text2:e.stack};
|
||||
}
|
||||
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 "index.html":
|
||||
response.writeHead(301, {"Location":'/'});
|
||||
return response.end();
|
||||
case "file":
|
||||
SendBlockFile(response, ArrPath[1], ArrPath[2]);
|
||||
break;
|
||||
case "DappTemplateFile":
|
||||
DappTemplateFile(response, ArrPath[1]);
|
||||
break;
|
||||
case "smart":
|
||||
DappSmartCodeFile(response, ArrPath[1]);
|
||||
break;
|
||||
case "client":
|
||||
DappClientCodeFile(response, ArrPath[1]);
|
||||
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 === "" || LangPathMap[Name])
|
||||
Name = IndexName;
|
||||
if(Name.indexOf(".") < 0)
|
||||
Name += ".html";
|
||||
var PrefixPath;
|
||||
if(Method === "files")
|
||||
{
|
||||
PrefixPath = "../FILES";
|
||||
Name = "";
|
||||
for(var i = 1; i < ArrPath.length; i++)
|
||||
if(ArrPath[i].indexOf("..") === - 1 && ArrPath[i].indexOf("\\") === - 1)
|
||||
Name += "/" + ArrPath[i];
|
||||
Name = PrefixPath + Name;
|
||||
SendWebFile(response, Name, Path);
|
||||
return ;
|
||||
}
|
||||
else
|
||||
if(LangPathMap[Method])
|
||||
{
|
||||
PrefixPath = "./SITE/" + Method;
|
||||
}
|
||||
else
|
||||
{
|
||||
var Name2 = WalletFileMap[Name];
|
||||
if(!Name2)
|
||||
PrefixPath = "./SITE";
|
||||
else
|
||||
{
|
||||
PrefixPath = "./HTML";
|
||||
if(typeof Name2 === "string")
|
||||
Name = Name2;
|
||||
}
|
||||
}
|
||||
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, "", 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
HostingCaller.GetCurrentInfo = function (Params)
|
||||
{
|
||||
if(typeof Params === "object" && Params.BlockChain == 1)
|
||||
{
|
||||
if(!global.USE_API_WALLET)
|
||||
return {result:0};
|
||||
}
|
||||
var MaxNumBlockDB = SERVER.GetMaxNumBlockDB();
|
||||
var Ret = {result:1, VersionNum:global.UPDATE_CODE_VERSION_NUM, NETWORK:global.NETWORK, MaxNumBlockDB:MaxNumBlockDB, CurBlockNum:GetCurrentBlockNumByTime(),
|
||||
MaxAccID:DApps.Accounts.GetMaxAccount(), MaxDappsID:DApps.Smart.GetMaxNum(), 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, NEW_SIGN_TIME:NEW_SIGN_TIME,
|
||||
PRICE_DAO:PRICE_DAO(MaxNumBlockDB), };
|
||||
if(typeof Params === "object" && Params.Diagram == 1)
|
||||
{
|
||||
var arrNames = ["MAX:ALL_NODES", "MAX:HASH_RATE_B"];
|
||||
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,response)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
Params.StartNum = ParseNum(Params.StartNum);
|
||||
Params.CountNum = ParseNum(Params.CountNum);
|
||||
if(Params.CountNum > MaxCountViewRows)
|
||||
Params.CountNum = MaxCountViewRows;
|
||||
if(!Params.CountNum)
|
||||
Params.CountNum = 1;
|
||||
return HTTPCaller.GetBlockList(Params, response);
|
||||
};
|
||||
HostingCaller.GetTransactionList = function (Params,response)
|
||||
{
|
||||
Params.Param3 = Params.BlockNum;
|
||||
return HostingCaller.GetTransactionAll(Params, response);
|
||||
};
|
||||
HostingCaller.GetTransactionAll = function (Params,response)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
Params.Param3 = ParseNum(Params.Param3);
|
||||
Params.StartNum = ParseNum(Params.StartNum);
|
||||
Params.CountNum = ParseNum(Params.CountNum);
|
||||
if(Params.CountNum > MaxCountViewRows)
|
||||
Params.CountNum = MaxCountViewRows;
|
||||
return HTTPCaller.GetTransactionAll(Params, response);
|
||||
};
|
||||
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), undefined, Params.Filter, 1);
|
||||
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 Geo = 0;
|
||||
if(typeof Params === "object" && Params.Geo)
|
||||
Geo = 1;
|
||||
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(Geo)
|
||||
{
|
||||
if(!Item.Geo)
|
||||
SetGeoLocation(Item);
|
||||
Value.latitude = Item.latitude;
|
||||
Value.longitude = Item.longitude;
|
||||
Value.name = Item.name;
|
||||
Value.port = Item.port;
|
||||
}
|
||||
arr.push(Value);
|
||||
}
|
||||
var Result = {result:1, arr:arr, VersionNum:global.UPDATE_CODE_VERSION_NUM, NETWORK:global.NETWORK, };
|
||||
return Result;
|
||||
};
|
||||
var AccountKeyMap = {};
|
||||
var LastMaxNum = 0;
|
||||
HostingCaller.GetAccountListByKey = function (Params,ppp,bRet)
|
||||
{
|
||||
if(typeof Params !== "object" || !Params.Key)
|
||||
return {result:0, arr:[]};
|
||||
if(!global.USE_API_WALLET)
|
||||
return {result:0};
|
||||
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 >= global.HTTP_MAX_COUNT_ROWS)
|
||||
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;
|
||||
};
|
||||
var CategoryMap = {};
|
||||
var CategoryArr = [];
|
||||
var CategoryDappMaxNumWas = 0;
|
||||
HostingCaller.GetDappCategory = function (Params,response)
|
||||
{
|
||||
CheckDappCategoryMap();
|
||||
return {result:1, arr:CategoryArr};
|
||||
};
|
||||
|
||||
function CheckDappCategoryMap()
|
||||
{
|
||||
var MaxNumNow = DApps.Smart.GetMaxNum();
|
||||
if(MaxNumNow !== CategoryDappMaxNumWas)
|
||||
{
|
||||
for(var Num = CategoryDappMaxNumWas; Num <= MaxNumNow; Num++)
|
||||
{
|
||||
var Item = DApps.Smart.ReadSimple(Num);
|
||||
for(var n = 1; n <= 3; n++)
|
||||
{
|
||||
var Name = "Category" + n;
|
||||
var Value = Item[Name];
|
||||
if(Value)
|
||||
{
|
||||
var DappMap = CategoryMap[Value];
|
||||
if(!DappMap)
|
||||
{
|
||||
DappMap = {};
|
||||
CategoryMap[Value] = DappMap;
|
||||
CategoryArr.push(Value);
|
||||
}
|
||||
DappMap[Num] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
CategoryDappMaxNumWas = MaxNumNow;
|
||||
}
|
||||
};
|
||||
HostingCaller.SendTransactionHex = function (Params,response)
|
||||
{
|
||||
if(typeof Params !== "object" || !Params.Hex)
|
||||
return {result:0, text:"object requre"};
|
||||
process.RunRPC("AddTransactionFromWeb", {HexValue: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,responce)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
return HTTPCaller.DappBlockFile(Params, responce);
|
||||
};
|
||||
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(Params.AllAccounts || Ret.arr[i].Value.Smart === Smart)
|
||||
{
|
||||
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,response)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
Params.StartNum = ParseNum(Params.StartNum);
|
||||
Params.CountNum = ParseNum(Params.CountNum);
|
||||
if(Params.CountNum > MaxCountViewRows)
|
||||
Params.CountNum = MaxCountViewRows;
|
||||
if(!Params.CountNum)
|
||||
Params.CountNum = 1;
|
||||
return HTTPCaller.DappBlockList(Params, response);
|
||||
};
|
||||
HostingCaller.DappTransactionList = function (Params,response)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
Params.BlockNum = ParseNum(Params.BlockNum);
|
||||
Params.StartNum = ParseNum(Params.StartNum);
|
||||
Params.CountNum = ParseNum(Params.CountNum);
|
||||
if(Params.CountNum > MaxCountViewRows)
|
||||
Params.CountNum = MaxCountViewRows;
|
||||
if(!Params.CountNum)
|
||||
Params.CountNum = 1;
|
||||
return HTTPCaller.DappTransactionList(Params, response);
|
||||
};
|
||||
HostingCaller.DappStaticCall = function (Params,response)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
return HTTPCaller.DappStaticCall(Params, response);
|
||||
};
|
||||
HostingCaller.GetHistoryTransactions = function (Params)
|
||||
{
|
||||
if(typeof Params !== "object")
|
||||
return {result:0};
|
||||
return HTTPCaller.GetHistoryTransactions(Params);
|
||||
};
|
||||
HostingCaller.GetSupply = function (Params)
|
||||
{
|
||||
var Data = DApps.Accounts.ReadState(0);
|
||||
if(!Data)
|
||||
return "";
|
||||
else
|
||||
{
|
||||
return "" + (global.TOTAL_SUPPLY_TERA - Data.Value.SumCOIN);
|
||||
}
|
||||
};
|
||||
HostingCaller.GetTotalSupply = function (Params)
|
||||
{
|
||||
return "" + global.TOTAL_SUPPLY_TERA;
|
||||
};
|
||||
global.GlobalRunID = 0;
|
||||
global.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});
|
||||
}
|
||||
};
|
||||
global.EvalCode = function (Code)
|
||||
{
|
||||
var Result;
|
||||
try
|
||||
{
|
||||
var ret = eval(Code);
|
||||
Result = JSON.stringify(ret, "", 4);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
Result = "" + e;
|
||||
}
|
||||
return Result;
|
||||
};
|
||||
setInterval(function ()
|
||||
{
|
||||
if(SERVER)
|
||||
SERVER.Close();
|
||||
DApps.Accounts.Close();
|
||||
DApps.Smart.DBSmart.Close();
|
||||
}, 500);
|
||||
setInterval(function ()
|
||||
{
|
||||
var MaxNumBlockDB = SERVER.GetMaxNumBlockDB();
|
||||
var HASHARATE_BLOCK_LENGTH = 10;
|
||||
var arr = SERVER.GetStatBlockchain("POWER_BLOCKCHAIN", HASHARATE_BLOCK_LENGTH);
|
||||
if(arr.length)
|
||||
{
|
||||
var SumPow = 0;
|
||||
var Count = 0;
|
||||
var Value = 0;
|
||||
for(var i = arr.length - HASHARATE_BLOCK_LENGTH; i < arr.length; i++)
|
||||
if(arr[i])
|
||||
{
|
||||
Value = arr[i];
|
||||
SumPow += Value;
|
||||
Count++;
|
||||
}
|
||||
if(!Count)
|
||||
Count = 1;
|
||||
var AvgPow = SumPow / Count;
|
||||
ADD_TO_STAT("MAX:HASH_RATE_B", AvgPow);
|
||||
}
|
||||
var Count = COUNT_BLOCK_PROOF + 16 - 1;
|
||||
if(MaxNumBlockDB > Count)
|
||||
{
|
||||
var StartNum = MaxNumBlockDB - Count;
|
||||
NodeBlockChain = SERVER.BlockChainToBuf(StartNum, StartNum, MaxNumBlockDB);
|
||||
}
|
||||
}, 700);
|
||||
require("./api-exchange.js");
|
||||
try
|
||||
{
|
||||
require("../SITE/JS/web-addon.js");
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
}
|
||||
global.LoadBlockFromNetwork = function (Params,F)
|
||||
{
|
||||
ToLog("RUN: LoadBlockFromNetwork:" + Params.BlockNum, 2);
|
||||
process.RunRPC("LoadBlockFromNetwork", {BlockNum:Params.BlockNum, F:1}, function (Err,Block)
|
||||
{
|
||||
ToLog("RETURN: LoadBlockFromNetwork: " + Params.BlockNum, 2);
|
||||
F(Err, Block);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user