forked from circlecloud/tera
		
	
							
								
								
									
										363
									
								
								src/process/api-exchange.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								src/process/api-exchange.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,363 @@
 | 
			
		||||
/*
 | 
			
		||||
 * @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
 | 
			
		||||
*/
 | 
			
		||||
let WebApi2: any = {};
 | 
			
		||||
import * as crypto from 'crypto';
 | 
			
		||||
WebApi2.GenerateKeys = function(Params) {
 | 
			
		||||
    var KeyPair = crypto.createECDH('secp256k1');
 | 
			
		||||
    var PrivKey = global.sha3(crypto.randomBytes(32));
 | 
			
		||||
    KeyPair.setPrivateKey(Buffer.from(PrivKey));
 | 
			
		||||
    var PubKey = KeyPair.getPublicKey('' as any, 'compressed');
 | 
			
		||||
    return { result: 1, PrivKey: global.GetHexFromArr(PrivKey), PubKey: global.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(global.GetArrFromHex(Params.PrivKey)));
 | 
			
		||||
        var PubKey = KeyPair.getPublicKey('' as any, 'compressed');
 | 
			
		||||
        var TR: any = { Type: global.TYPE_TRANSACTION_CREATE, Currency: Params.Currency, PubKey: PubKey, Name: Params.Name, Smart: Params.Smart, };
 | 
			
		||||
        var Body = global.BufLib.GetBufferFromObject(TR, global.FORMAT_CREATE, 1000, {}, 1);
 | 
			
		||||
        Body = Body.slice(0, Body.len + 12);
 | 
			
		||||
        SendTransaction(Body, TR as any, Params.Wait, function(result, text) {
 | 
			
		||||
            var Result = {
 | 
			
		||||
                result: result, text: text, TxID: global.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 = global.GetArrFromHex(Params.ToID);
 | 
			
		||||
    else
 | 
			
		||||
        ToID = ParseNum(Params.ToID);
 | 
			
		||||
    var DataFrom = global.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 = global.DApps.Accounts.GetSignTransferTx(TR, global.GetArrFromHex(Params.FromPrivKey));
 | 
			
		||||
    var Body = global.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: global.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 = global.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: global.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 = global.GetArrFromHex(Params.TxID);
 | 
			
		||||
        var BlockNum = ReadUintFromArr(Arr, TR_TICKET_HASH_LENGTH);
 | 
			
		||||
        var Block = global.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 (global.CompareArr(Arr2, Arr) === 0) {
 | 
			
		||||
                    return GetTransactionFromBody(Params, Block, i, Body);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        if (typeof Params === "object" && Params.BlockNum && Params.TrNum !== undefined) {
 | 
			
		||||
            var Block = global.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 = global.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 = global.SERVER.ReadBlockDB(Item.BlockNum);
 | 
			
		||||
                if (!Block || (!Block.arrContent))
 | 
			
		||||
                    continue;
 | 
			
		||||
                var Body = Block.arrContent[Item.TrNum];
 | 
			
		||||
                if (!Body)
 | 
			
		||||
                    continue;
 | 
			
		||||
                if (Params.GetTxID) {
 | 
			
		||||
                    Item.TxID = global.GetHexFromArr(GetTxID(Item.BlockNum, Body));
 | 
			
		||||
                }
 | 
			
		||||
                if (Params.GetDescription) {
 | 
			
		||||
                    var TR = global.DApps.Accounts.GetObjectTransaction(Body);
 | 
			
		||||
                    if (TR) {
 | 
			
		||||
                        Item.Description = TR.Description;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        var Result = { result: arr.length > 0 ? 1 : 0, History: arr, Tail: global.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 = global.DApps.Accounts.GetSignTransferTx(TR, global.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 = global.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: global.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 = global.GetHexFromArr(TR.To[0].PubKey);
 | 
			
		||||
        else
 | 
			
		||||
            TR.To[0].PubKey = "";
 | 
			
		||||
        if (TR.Sign && TR.Sign.length)
 | 
			
		||||
            TR.Sign = global.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 = global.GetArrFromHex(TR.Sign);
 | 
			
		||||
    else
 | 
			
		||||
        TR.Sign = [];
 | 
			
		||||
    for (var i = 0; i < TR.To.length; i++) {
 | 
			
		||||
        TR.To[i].PubKey = global.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 = global.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] === global.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;
 | 
			
		||||
            global.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: global.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++;
 | 
			
		||||
                        global.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 = global.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
									
								
								src/process/dogs.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/process/dogs.ts
									
									
									
									
									
										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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										732
									
								
								src/process/main-process.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										732
									
								
								src/process/main-process.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,732 @@
 | 
			
		||||
/*
 | 
			
		||||
 * @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
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
import '../core/constant'
 | 
			
		||||
global.PROCESS_NAME = "MAIN";
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const os = require('os');
 | 
			
		||||
import * as crypto from 'crypto';
 | 
			
		||||
 | 
			
		||||
let {
 | 
			
		||||
    GetNormalPathString,
 | 
			
		||||
    sha3,
 | 
			
		||||
    AddTrMap,
 | 
			
		||||
    ADD_HASH_RATE
 | 
			
		||||
} = global
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
global.ToLog(os.platform() + " (" + os.arch() + ") " + os.release());
 | 
			
		||||
var VerArr = process.versions.node.split('.');
 | 
			
		||||
global.ToLog("nodejs: " + process.versions.node);
 | 
			
		||||
if ((VerArr[0] as any as number) < 8) {
 | 
			
		||||
    global.global.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": "60.12.241.181", "port": 30000 },
 | 
			
		||||
    { "ip": "60.12.241.181", "port": 30001 },
 | 
			
		||||
    { "ip": "60.12.241.181", "port": 30002 },
 | 
			
		||||
    { "ip": "60.12.241.181", "port": 30003 },
 | 
			
		||||
    { "ip": "60.12.241.181", "port": 30004 },
 | 
			
		||||
    { "ip": "60.12.241.181", "port": 30005 },];
 | 
			
		||||
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' as any, function(err: TeraError) {
 | 
			
		||||
    if (global.PROCESS_NAME !== "MAIN") {
 | 
			
		||||
        process.send({ cmd: "log", message: err });
 | 
			
		||||
    }
 | 
			
		||||
    global.global.ToError(err.stack);
 | 
			
		||||
    global.ToLog(err.stack);
 | 
			
		||||
    if (err.code === "ENOTFOUND" || err.code === "ECONNRESET" || err.code === "EPIPE") {
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        global.TO_ERROR_LOG("APP", 666, err);
 | 
			
		||||
        global.ToLog("-----------------EXIT------------------");
 | 
			
		||||
        process.exit();
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
process.on('error' as any, function(err: TeraError) {
 | 
			
		||||
    global.global.ToError(err.stack);
 | 
			
		||||
    global.ToLog(err.stack);
 | 
			
		||||
});
 | 
			
		||||
var ArrChildProcess = [];
 | 
			
		||||
var WebProcess: TeraProcess = {
 | 
			
		||||
    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 = global.SERVER.GetDirectNodesArray(true, true).slice(1, 500);
 | 
			
		||||
            var arr2 = [];
 | 
			
		||||
            var CurTime = global.GetCurrentTime() - 0;
 | 
			
		||||
            for (var i = 0; i < global.SERVER.NodesArr.length; i++) {
 | 
			
		||||
                var Item = global.SERVER.NodesArr[i];
 | 
			
		||||
                if (Item.LastTime && (CurTime - Item.LastTime) < global.NODES_DELTA_CALC_HOUR * 3600 * 1000)
 | 
			
		||||
                    arr2.push({ ip: Item.ip, port: Item.port, webport: Item.webport });
 | 
			
		||||
                else
 | 
			
		||||
                    if (Item.LastTimeGetNode && (CurTime - Item.LastTimeGetNode) < global.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 = global.GetArrFromHex(Params.HexValue);
 | 
			
		||||
    if (global.TX_PROCESS && global.TX_PROCESS.Worker) {
 | 
			
		||||
        var StrHex = global.GetHexFromArr(sha3(body));
 | 
			
		||||
        global.TX_PROCESS.Worker.send({ cmd: "FindTX", TX: StrHex, Web: 1, WebID: Params.WebID });
 | 
			
		||||
    }
 | 
			
		||||
    var Res = global.SERVER.AddTransaction({ body: body }, 1);
 | 
			
		||||
    var text = AddTrMap[Res];
 | 
			
		||||
    var final = false;
 | 
			
		||||
    if (Res <= 0 && Res !== - 3)
 | 
			
		||||
        final = true;
 | 
			
		||||
    global.ToLogClient("Send: " + text, global.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(global.STATIC_PROCESS);
 | 
			
		||||
 | 
			
		||||
function OnMessageStatic(msg) {
 | 
			
		||||
    switch (msg.cmd) {
 | 
			
		||||
        case "Send":
 | 
			
		||||
            {
 | 
			
		||||
                var Node = global.SERVER.NodesMap[msg.addrStr];
 | 
			
		||||
                if (Node) {
 | 
			
		||||
                    msg.Data = msg.Data.data;
 | 
			
		||||
                    global.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(global.TX_PROCESS);
 | 
			
		||||
 | 
			
		||||
function OnMessageTX(msg) {
 | 
			
		||||
    switch (msg.cmd) {
 | 
			
		||||
        case "DappEvent":
 | 
			
		||||
            {
 | 
			
		||||
                if (WebProcess && WebProcess.Worker) {
 | 
			
		||||
                    WebProcess.Worker.send(msg);
 | 
			
		||||
                }
 | 
			
		||||
                global.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 && global.DApps.Accounts) {
 | 
			
		||||
                global.DApps.Accounts.Close();
 | 
			
		||||
                global.DApps.Smart.DBSmart.Close();
 | 
			
		||||
            }
 | 
			
		||||
            if (global.WALLET && global.DApps.DBHistory)
 | 
			
		||||
                global.DApps.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) {
 | 
			
		||||
                    global.ToLog("KILL PROCESS " + ITEM.Name + ": " + ITEM.Worker.pid);
 | 
			
		||||
                    try {
 | 
			
		||||
                        process.kill(ITEM.Worker.pid, 'SIGKILL');
 | 
			
		||||
                    }
 | 
			
		||||
                    catch (e) {
 | 
			
		||||
                        global.ToLog("ERR KILL");
 | 
			
		||||
                    }
 | 
			
		||||
                    ITEM.Worker = undefined;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (!ITEM.Worker) {
 | 
			
		||||
                ITEM.LastAlive = (Date.now()) + ITEM.PeriodAlive * 3;
 | 
			
		||||
                global.ToLog("STARTING " + ITEM.Name);
 | 
			
		||||
                ITEM.Worker = Fork(ITEM.Path, ["READONLYDB"]);
 | 
			
		||||
                ITEM.pid = ITEM.Worker.pid;
 | 
			
		||||
                global.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":
 | 
			
		||||
                            global.ToLog(msg.message);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case "global.ToLogClient":
 | 
			
		||||
                            if (WebProcess && WebProcess.Worker) {
 | 
			
		||||
                                WebProcess.Worker.send(msg);
 | 
			
		||||
                            }
 | 
			
		||||
                            global.ToLogClient(msg.Str, msg.StrKey, msg.bFinal);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case "RetFindTX":
 | 
			
		||||
                            if (WebProcess && WebProcess.Worker) {
 | 
			
		||||
                                WebProcess.Worker.send(msg);
 | 
			
		||||
                                if (msg.Web)
 | 
			
		||||
                                    break;
 | 
			
		||||
                            }
 | 
			
		||||
                            global.ToLogClient(msg.ResultStr, msg.TX, msg.bFinal);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case "online":
 | 
			
		||||
                            if (ITEM.Worker)
 | 
			
		||||
                                global.ToLog("RUNNING " + ITEM.Name + " : " + msg.message + " pid: " + ITEM.Worker.pid);
 | 
			
		||||
                            break;
 | 
			
		||||
                        case "WriteBodyResult":
 | 
			
		||||
                            var Block = global.SERVER.ReadBlockDB(msg.BlockNum);
 | 
			
		||||
                            if (Block) {
 | 
			
		||||
                                Block.arrContentResult = msg.arrContentResult;
 | 
			
		||||
                                global.SERVER.WriteBodyResultDB(Block);
 | 
			
		||||
                            }
 | 
			
		||||
                            break;
 | 
			
		||||
                        default:
 | 
			
		||||
                            if (ITEM.OnMessage) {
 | 
			
		||||
                                ITEM.OnMessage(msg);
 | 
			
		||||
                            }
 | 
			
		||||
                            break;
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                ITEM.Worker.on('error', function(err) {
 | 
			
		||||
                });
 | 
			
		||||
                ITEM.Worker.on('close', function(code) {
 | 
			
		||||
                    global.global.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();
 | 
			
		||||
let {
 | 
			
		||||
    ArrReconnect,
 | 
			
		||||
    ArrConnect
 | 
			
		||||
} = global
 | 
			
		||||
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) {
 | 
			
		||||
    // @ts-ignore
 | 
			
		||||
    return;
 | 
			
		||||
}
 | 
			
		||||
let ArrMiningWrk = global.ArrMiningWrk
 | 
			
		||||
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 = [];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
let {
 | 
			
		||||
    GetCountMiningCPU,
 | 
			
		||||
    CHECK_RUN_MINING,
 | 
			
		||||
    GetSecFromStrTime,
 | 
			
		||||
    SERVER,
 | 
			
		||||
    GENERATE_BLOCK_ACCOUNT,
 | 
			
		||||
    GetCodePath,
 | 
			
		||||
    GrayConnect
 | 
			
		||||
} = global
 | 
			
		||||
 | 
			
		||||
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 = global.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) {
 | 
			
		||||
            global.ToLog("------------ MINING MUST STOP ON TIME");
 | 
			
		||||
            ClearArrMining();
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
            if (!ArrMiningWrk.length && !global.MiningPaused) {
 | 
			
		||||
                global.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()) {
 | 
			
		||||
        global.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) {
 | 
			
		||||
            global.ToLog("Not enough memory to start processes.");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    ProcessMemorySize = Math.trunc(Memory / GetCountMiningCPU());
 | 
			
		||||
    global.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") {
 | 
			
		||||
                global.ToLog(msg.message);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                if (msg.cmd === "online") {
 | 
			
		||||
                    Worker.bOnline = true;
 | 
			
		||||
                    global.ToLog("RUNNING PROCESS:" + Worker.Num + ":" + msg.message);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    if (msg.cmd === "POW") {
 | 
			
		||||
                        global.SERVER.MiningProcess(msg);
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                        if (msg.cmd === "HASHRATE") {
 | 
			
		||||
                            ADD_HASH_RATE(msg.CountNonce);
 | 
			
		||||
                        }
 | 
			
		||||
        });
 | 
			
		||||
        Worker.on('error', function(err) {
 | 
			
		||||
            if (!ArrMiningWrk.length)
 | 
			
		||||
                return;
 | 
			
		||||
            global.global.ToError('ERROR IN PROCESS: ' + err);
 | 
			
		||||
        });
 | 
			
		||||
        Worker.on('close', function(code) {
 | 
			
		||||
            global.ToLog("STOP PROCESS: " + Worker.Num + " pid:" + Worker.pid);
 | 
			
		||||
            for (var i = 0; i < ArrMiningWrk.length; i++) {
 | 
			
		||||
                if (ArrMiningWrk[i].pid === Worker.pid) {
 | 
			
		||||
                    global.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;
 | 
			
		||||
let {
 | 
			
		||||
    glCurNumFindArr
 | 
			
		||||
} = global
 | 
			
		||||
function DoGetNodes() {
 | 
			
		||||
    if (!SERVER)
 | 
			
		||||
        return;
 | 
			
		||||
    if (!GrayConnect() && global.SERVER.CanSend < 2)
 | 
			
		||||
        return;
 | 
			
		||||
    if (!SERVER.NodesArrUnSort || !SERVER.NodesArrUnSort.length)
 | 
			
		||||
        return;
 | 
			
		||||
    var Num = glCurNumFindArr % global.SERVER.NodesArrUnSort.length;
 | 
			
		||||
    var Node = global.SERVER.NodesArrUnSort[Num];
 | 
			
		||||
    if (Num === 0)
 | 
			
		||||
        glCurNumFindArr = 0;
 | 
			
		||||
    glCurNumFindArr++;
 | 
			
		||||
    if (Node.Delete)
 | 
			
		||||
        return;
 | 
			
		||||
    if (SERVER.NodeInBan(Node))
 | 
			
		||||
        return;
 | 
			
		||||
    if (SERVER.BusyLevel && Node.BlockProcessCount <= global.SERVER.BusyLevel)
 | 
			
		||||
        return;
 | 
			
		||||
    if (GetSocketStatus(Node.Socket) === 100) {
 | 
			
		||||
        global.SERVER.StartGetNodes(Node);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function DoConnectToNodes(Arr, Mode) {
 | 
			
		||||
    if (!SERVER)
 | 
			
		||||
        return;
 | 
			
		||||
    if (!GrayConnect() && global.SERVER.CanSend < 2) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (GrayConnect() && global.SERVER.ActualNodes.size > GetGrayServerConnections())
 | 
			
		||||
        return;
 | 
			
		||||
    if (Arr.length) {
 | 
			
		||||
        var MinProcessCount = global.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;
 | 
			
		||||
                    global.SERVER.StartConnectTry(Node);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                    if (Mode === "RECONNECT") {
 | 
			
		||||
                        Node.WasAddToReconnect = undefined;
 | 
			
		||||
                        Node.CreateConnect();
 | 
			
		||||
                    }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
var idRunOnce;
 | 
			
		||||
 | 
			
		||||
function RunServer() {
 | 
			
		||||
    let {
 | 
			
		||||
        GetNetworkName,
 | 
			
		||||
        DEF_VERSION,
 | 
			
		||||
        NET_WORK_MODE,
 | 
			
		||||
        SAVE_CONST,
 | 
			
		||||
        ToLog,
 | 
			
		||||
        START_IP,
 | 
			
		||||
        START_PORT_NUMBER
 | 
			
		||||
    } = global
 | 
			
		||||
    idRunOnce = setInterval(RunOnce, 1000);
 | 
			
		||||
    global.ToLog("NETWORK: " + GetNetworkName());
 | 
			
		||||
    global.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: any = KeyPair.getPublicKey('' as any, 'compressed');
 | 
			
		||||
            if (Arr2[0] === 2)
 | 
			
		||||
                break;
 | 
			
		||||
        }
 | 
			
		||||
        global.SERVER_PRIVATE_KEY_HEX = global.GetHexFromArr(Arr);
 | 
			
		||||
        SAVE_CONST(true);
 | 
			
		||||
    }
 | 
			
		||||
    var ServerPrivKey = global.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 = global.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 = global.SERVER.ip + ":" + global.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 = global.GetHexFromAddres(crypto.randomBytes(32));
 | 
			
		||||
        var Node = global.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 = (global.random(600) + global.RESTART_PERIOD_SEC);
 | 
			
		||||
            global.ToLog("SET RESTART NODE AFTER: " + Period + " sec");
 | 
			
		||||
            setInterval(function() {
 | 
			
		||||
                RestartNode();
 | 
			
		||||
            }, Period * 1000);
 | 
			
		||||
        }
 | 
			
		||||
        setTimeout(function() {
 | 
			
		||||
            global.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(global.GetArrFromHex("A6B0914953F515F4686B2BA921B8FAC66EE6A6D3E317B43E981EBBA52393BFC6"));
 | 
			
		||||
    var PubKey = Buffer.from(global.GetArrFromHex("026A04AB98D9E4774AD806E302DDDEB63BEA16B5CB5F223EE77478E861BB583EB3"));
 | 
			
		||||
    var Sign = Buffer.from(global.GetArrFromHex("5D5382C65E4C1E8D412D5F30F87B8F72F371E9E4FC170761BCE583A961CF44966F92B38D402BC1CBCB7567335051A321B93F4E32112129AED4AB602E093A1187"));
 | 
			
		||||
    var startTime = process.hrtime();
 | 
			
		||||
    var deltaTime = 1;
 | 
			
		||||
    for (var Num = 0; Num < 1000; Num++) {
 | 
			
		||||
        var Result = global.secp256k1.verify(hash, Sign, PubKey);
 | 
			
		||||
        if (!Result) {
 | 
			
		||||
            global.global.ToError("Error test sign");
 | 
			
		||||
            process.exit(0);
 | 
			
		||||
        }
 | 
			
		||||
        var Time = process.hrtime(startTime);
 | 
			
		||||
        deltaTime = Time[0] * 1000 + Time[1] / 1e6;
 | 
			
		||||
        if (deltaTime > MaxTime) {
 | 
			
		||||
            global.ToLog("*************** WARNING: VERY SLOW LIBRARY: secp256k1 ***************");
 | 
			
		||||
            global.ToLog("You can only process: " + Num + " transactions");
 | 
			
		||||
            global.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);
 | 
			
		||||
    global.ToLog("TestSignLib: " + global.SpeedSignLib + " per sec");
 | 
			
		||||
    return 1;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										91
									
								
								src/process/pow-process.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								src/process/pow-process.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
/*
 | 
			
		||||
 * @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: any = {};
 | 
			
		||||
 | 
			
		||||
function CheckAlive() {
 | 
			
		||||
    if (!global.NOALIVE) {
 | 
			
		||||
        var e = Date.now() - LastAlive;
 | 
			
		||||
        Math.abs(e) > global.CHECK_STOP_CHILD_PROCESS && PROCESS.exit(0);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function CalcPOWHash() {
 | 
			
		||||
    if (Block.SeqHash) {
 | 
			
		||||
        if ((new Date as any) - Block.Time > Block.Period)
 | 
			
		||||
            return clearInterval(idInterval), void (idInterval = void 0);
 | 
			
		||||
        try {
 | 
			
		||||
            global.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) {
 | 
			
		||||
            global.global.ToError(e);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
PROCESS.on("message", function(e) {
 | 
			
		||||
    if (LastAlive = Date.now(), "FastCalcBlock" === e.cmd) {
 | 
			
		||||
        var o = e;
 | 
			
		||||
        StartHashPump(o), o.RunCount = 0;
 | 
			
		||||
        try {
 | 
			
		||||
            global.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) {
 | 
			
		||||
            global.global.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 = global.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) {
 | 
			
		||||
    (!global.BlockPump || global.BlockPump.BlockNum < e.BlockNum || global.BlockPump.MinerID !== e.MinerID || global.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 (global.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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										373
									
								
								src/process/static-process.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								src/process/static-process.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,373 @@
 | 
			
		||||
/*
 | 
			
		||||
 * @project: TERA
 | 
			
		||||
 * @version: Development (beta)
 | 
			
		||||
 * @license: MIT (not for evil)
 | 
			
		||||
 * @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
 | 
			
		||||
 * Web: https://terafoundation.org
 | 
			
		||||
 * Twitter: https://twitter.com/terafoundation
 | 
			
		||||
 * Telegram:  https://t.me/terafoundation
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
global.PROCESS_NAME = "STATIC";
 | 
			
		||||
import * as crypto from 'crypto';
 | 
			
		||||
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) {
 | 
			
		||||
        global.ToLog("STATIC-DB: ALIVE TIMEOUT Stop and exit: " + Delta + "/" + global.CHECK_STOP_CHILD_PROCESS);
 | 
			
		||||
        process.exit(0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
process.on('uncaughtException', function(err) {
 | 
			
		||||
    global.ToError(err.stack);
 | 
			
		||||
    global.ToLog(err.stack);
 | 
			
		||||
    TO_ERROR_LOG("STATIC-DB", 777, err);
 | 
			
		||||
    global.ToLog("-----------------STATIC-DB EXIT------------------");
 | 
			
		||||
    process.exit();
 | 
			
		||||
});
 | 
			
		||||
process.on('error', function(err) {
 | 
			
		||||
    global.ToError("STATIC-DB:\n" + err.stack);
 | 
			
		||||
    global.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)
 | 
			
		||||
        global.SERVER.Close();
 | 
			
		||||
    global.DApps.Accounts.Close();
 | 
			
		||||
    global.DApps.Smart.DBSmart.Close();
 | 
			
		||||
}, 1000);
 | 
			
		||||
 | 
			
		||||
function GETBLOCKHEADER100(msg) {
 | 
			
		||||
    return;
 | 
			
		||||
    var Data = msg.Data;
 | 
			
		||||
    var BlockNum = Data.BlockNum;
 | 
			
		||||
    if (BlockNum % 100 !== 0)
 | 
			
		||||
        return;
 | 
			
		||||
    var EndNum100 = BlockNum / 100;
 | 
			
		||||
    var LoadHash100 = Data.Hash;
 | 
			
		||||
    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 = global.SERVER.DBHeader100.Read(EndNum100);
 | 
			
		||||
    if (Data100 && global.CompareArr(Data100.Hash100, LoadHash100) === 0) {
 | 
			
		||||
        var StartNum = EndNum100 - Count + 1;
 | 
			
		||||
        if (StartNum < 0)
 | 
			
		||||
            StartNum = 0;
 | 
			
		||||
        for (var Num = StartNum; Num <= EndNum100; Num++) {
 | 
			
		||||
            Data100 = global.SERVER.DBHeader100.Read(Num);
 | 
			
		||||
            if (Num === StartNum)
 | 
			
		||||
                Arr.push(Data100.Hash100);
 | 
			
		||||
            Arr.push(Data100.Hash);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    var BufWrite = global.BufLib.GetBufferFromObject(Arr, "[hash]", MAX_PACKET_LENGTH, {});
 | 
			
		||||
    global.ToLog("GETBLOCKHEADER100 Send Arr=" + Arr.length + " - " + BlockNum);
 | 
			
		||||
    process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETBLOCKHEADER100", Context: msg.Context, Data: BufWrite });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function GETBLOCKHEADER(msg) {
 | 
			
		||||
    var Data = msg.Data;
 | 
			
		||||
    var StartNum = undefined;
 | 
			
		||||
    var BlockNum;
 | 
			
		||||
    var LoadHash = Data.Hash;
 | 
			
		||||
    var Foward = Data.Foward;
 | 
			
		||||
    if (Foward) {
 | 
			
		||||
        var BlockDB = global.SERVER.ReadBlockHeaderDB(Data.BlockNum);
 | 
			
		||||
        if (BlockDB && BlockDB.SumHash && (global.CompareArr(BlockDB.SumHash, LoadHash) === 0 || IsZeroArr(LoadHash))) {
 | 
			
		||||
            StartNum = Data.BlockNum - global.BLOCK_PROCESSING_LENGTH2;
 | 
			
		||||
            if (StartNum < 0)
 | 
			
		||||
                StartNum = 0;
 | 
			
		||||
            BlockNum = StartNum + COUNT_BLOCKS_FOR_LOAD + global.BLOCK_PROCESSING_LENGTH2;
 | 
			
		||||
            if (BlockNum > global.SERVER.GetMaxNumBlockDB())
 | 
			
		||||
                BlockNum = global.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 += global.BLOCK_PROCESSING_LENGTH2;
 | 
			
		||||
        var BlockDB = global.SERVER.ReadBlockHeaderDB(BlockNum);
 | 
			
		||||
        if (BlockDB && (BlockDB.Prepared && (!IsSum) && BlockDB.Hash && global.CompareArr(BlockDB.Hash, LoadHash) === 0 || BlockDB.bSave && IsSum && BlockDB.SumHash && global.CompareArr(BlockDB.SumHash,
 | 
			
		||||
            LoadHash) === 0)) {
 | 
			
		||||
            StartNum = BlockNum - Count + 1;
 | 
			
		||||
            if (StartNum < 0)
 | 
			
		||||
                StartNum = 0;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    var BufWrite = global.SERVER.BlockChainToBuf(StartNum, StartNum, BlockNum);
 | 
			
		||||
    process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETBLOCKHEADER", Context: msg.Context, Data: BufWrite });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function GETBLOCK(msg) {
 | 
			
		||||
    var Data = msg.Data;
 | 
			
		||||
    var BlockNum = Data.BlockNum;
 | 
			
		||||
    var TreeHash = Data.TreeHash;
 | 
			
		||||
    if (msg.Context.SendCount) {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    var BufWrite;
 | 
			
		||||
    var BlockDB = global.SERVER.ReadBlockDB(BlockNum);
 | 
			
		||||
    var StrSend;
 | 
			
		||||
    if (BlockDB && (global.CompareArr(BlockDB.TreeHash, TreeHash) === 0 || IsZeroArr(TreeHash))) {
 | 
			
		||||
        var BufWrite = global.BufLib.GetBufferFromObject(BlockDB, FORMAT_BLOCK_TRANSFER, MAX_PACKET_LENGTH, WRK_BLOCK_TRANSFER);
 | 
			
		||||
        StrSend = "OK";
 | 
			
		||||
    }
 | 
			
		||||
    if (StrSend === "OK") {
 | 
			
		||||
        global.ADD_TO_STAT("BLOCK_SEND");
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        BufWrite = global.BufLib.GetNewBuffer(100);
 | 
			
		||||
        StrSend = "NO";
 | 
			
		||||
    }
 | 
			
		||||
    process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETGETBLOCK", Context: msg.Context, Data: BufWrite });
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function GETCODE(msg) {
 | 
			
		||||
    var VersionNum = msg.Data;
 | 
			
		||||
    var fname = global.GetDataPath("Update/wallet-" + VersionNum + ".zip");
 | 
			
		||||
    if (fs.existsSync(fname)) {
 | 
			
		||||
        var data = fs.readFileSync(fname);
 | 
			
		||||
        process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETCODE", Context: msg.Context, Data: data });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function GETREST(msg) {
 | 
			
		||||
    var Data = msg.Data;
 | 
			
		||||
    if (!Data.BlockNum)
 | 
			
		||||
        return;
 | 
			
		||||
    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 = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
 | 
			
		||||
        var WorkFormatLength = global.DApps.Accounts.SIZE_ACCOUNT_ROW;
 | 
			
		||||
        var Max = global.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 (global.CompareArr(Data.AccHash, Tree.Root) !== 0) {
 | 
			
		||||
            global.ToLog("Get bad rest acc hash: " + BlockNumRest + " = " + global.GetHexFromArr(Data.AccHash) + "/" + global.GetHexFromArr(Tree.Root), 2);
 | 
			
		||||
            ArrRest = [];
 | 
			
		||||
            nResult = 0;
 | 
			
		||||
        }
 | 
			
		||||
        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 = global.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 = global.DApps.Smart.DBSmart.Read(Num, 1);
 | 
			
		||||
        if (!BufSmart)
 | 
			
		||||
            break;
 | 
			
		||||
        SizeForSend = SizeForSend - BufSmart.length;
 | 
			
		||||
        if (SizeForSend < 0)
 | 
			
		||||
            break;
 | 
			
		||||
        BufLength += BufSmart.length;
 | 
			
		||||
        Arr.push(BufSmart);
 | 
			
		||||
    }
 | 
			
		||||
    var Data2 = { Result: Arr.length ? 1 : 0, Arr: Arr };
 | 
			
		||||
    var BufWrite = global.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 = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
 | 
			
		||||
    var WorkFormatLength = global.DApps.Accounts.SIZE_ACCOUNT_ROW;
 | 
			
		||||
    for (var Num = StartAccount; Num <= EndAccount; Num++) {
 | 
			
		||||
        var FindItem = undefined;
 | 
			
		||||
        var RestData = global.DApps.Accounts.ReadRest(Num);
 | 
			
		||||
        var CountZero = 0;
 | 
			
		||||
        for (var i = RestData.Arr.length - 1; i >= 0; i--) {
 | 
			
		||||
            var Item = RestData.Arr[i];
 | 
			
		||||
            if (!Item.BlockNum) {
 | 
			
		||||
                CountZero++;
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            if (Item.BlockNum <= BlockNumRest) {
 | 
			
		||||
                if (!FindItem || Item.BlockNum > FindItem.BlockNum) {
 | 
			
		||||
                    FindItem = Item;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        var BlocNumMap = 0;
 | 
			
		||||
        var StateDataValue = undefined;
 | 
			
		||||
        if (FindItem) {
 | 
			
		||||
            StateDataValue = FindItem.Value;
 | 
			
		||||
            BlocNumMap = Item.BlockNum;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            if (CountZero !== RestData.Arr.length)
 | 
			
		||||
                continue;
 | 
			
		||||
        }
 | 
			
		||||
        var StateData = global.DApps.Accounts.DBState.Read(Num);
 | 
			
		||||
        if (!StateData)
 | 
			
		||||
            break;
 | 
			
		||||
        if (StateDataValue)
 | 
			
		||||
            StateData.Value = StateDataValue;
 | 
			
		||||
        if (bHashOnly) {
 | 
			
		||||
            var key = "" + Num + "-" + BlocNumMap;
 | 
			
		||||
            var Hash = glMapForHash[key];
 | 
			
		||||
            if (!Hash) {
 | 
			
		||||
                var Buf = global.BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
 | 
			
		||||
                Hash = global.shaarr(Buf);
 | 
			
		||||
                glMapForHash[key] = Hash;
 | 
			
		||||
            }
 | 
			
		||||
            ArrRest.push(Hash);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            var Buf = global.BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
 | 
			
		||||
            ArrRest.push(Buf);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return ArrRest;
 | 
			
		||||
};
 | 
			
		||||
var glMapRest = {};
 | 
			
		||||
 | 
			
		||||
function GetRestMerkleTree(BlockNumRest, RestIndexArr) {
 | 
			
		||||
    var MerkleTree = glMapRest[BlockNumRest];
 | 
			
		||||
    if (!MerkleTree) {
 | 
			
		||||
        global.ToLog("Create new glMapRest key: " + BlockNumRest, 2);
 | 
			
		||||
        var startTime = process.hrtime();
 | 
			
		||||
        var EndAccount = global.DApps.Accounts.DBState.GetMaxNum();
 | 
			
		||||
        var ArrHash = GetArrRest(BlockNumRest, 0, EndAccount, 1);
 | 
			
		||||
        var Time1 = process.hrtime(startTime);
 | 
			
		||||
        var MerkleCalc = {};
 | 
			
		||||
        MerkleTree = { LevelsHash: [ArrHash], RecalcCount: 0 };
 | 
			
		||||
        for (var Num = 0; Num < ArrHash.length; Num++) {
 | 
			
		||||
            MerkleCalc[Num] = 1;
 | 
			
		||||
        }
 | 
			
		||||
        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;
 | 
			
		||||
        global.ToLog("Create delta time: " + deltaTime1 + "/" + deltaTime2 + " s   Tree.Root=" + global.GetHexFromArr(MerkleTree.Root), 2);
 | 
			
		||||
        var MapIndex = {};
 | 
			
		||||
        for (var i = 0; i < RestIndexArr.length; i++) {
 | 
			
		||||
            MapIndex[RestIndexArr[i]] = 1;
 | 
			
		||||
        }
 | 
			
		||||
        for (var key in glMapRest) {
 | 
			
		||||
            if (!MapIndex[key]) {
 | 
			
		||||
                global.ToLog("Delete old glMapRest key: " + key, 2);
 | 
			
		||||
                delete glMapRest[key];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return MerkleTree;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										354
									
								
								src/process/tx-process.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								src/process/tx-process.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,354 @@
 | 
			
		||||
/*
 | 
			
		||||
 * @project: TERA
 | 
			
		||||
 * @version: Development (beta)
 | 
			
		||||
 * @license: MIT (not for evil)
 | 
			
		||||
 * @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
 | 
			
		||||
 * Web: https://terafoundation.org
 | 
			
		||||
 * Twitter: https://twitter.com/terafoundation
 | 
			
		||||
 * Telegram:  https://t.me/terafoundation
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
global.PROCESS_NAME = "TX";
 | 
			
		||||
import * as crypto from 'crypto';
 | 
			
		||||
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) {
 | 
			
		||||
        global.ToLog("TX-PROCESS: ALIVE TIMEOUT Stop and exit: " + Delta);
 | 
			
		||||
        process.exit(0);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
process.on('uncaughtException', function(err) {
 | 
			
		||||
    global.ToError(err.stack);
 | 
			
		||||
    global.ToLog(err.stack);
 | 
			
		||||
    TO_ERROR_LOG("TX-PROCESS", 777, err);
 | 
			
		||||
    global.ToLog("-----------------TX-PROCESS EXIT------------------");
 | 
			
		||||
    process.exit();
 | 
			
		||||
});
 | 
			
		||||
process.on('error', function(err) {
 | 
			
		||||
    global.ToError("TX-PROCESS:\n" + err.stack);
 | 
			
		||||
    global.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) {
 | 
			
		||||
        global.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)
 | 
			
		||||
            global.ToLog("!BlockMin");
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    var StartTime = Date.now();
 | 
			
		||||
    if (bShowDetail)
 | 
			
		||||
        global.ToLog("BlockMin: " + BlockMin.BlockNum + "  LastBlockNum=" + LastBlockNum);
 | 
			
		||||
    var CountTX = 0;
 | 
			
		||||
    for (var Num = BlockMin.BlockNum; Num < BlockMin.BlockNum + 200; Num++) {
 | 
			
		||||
        var EndTime = Date.now();
 | 
			
		||||
        var Delta = EndTime - StartTime;
 | 
			
		||||
        if (Delta >= 1000)
 | 
			
		||||
            break;
 | 
			
		||||
        var Block = global.SERVER.ReadBlockDB(Num);
 | 
			
		||||
        if (!Block) {
 | 
			
		||||
            if (bShowDetail)
 | 
			
		||||
                global.ToLog("!Block");
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        if (!IsValidSumHash(Block)) {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        var Item = BlockTree.LoadValue(Block.BlockNum, 1);
 | 
			
		||||
        if (Item && global.CompareArr(Item.SumHash, Block.SumHash) === 0) {
 | 
			
		||||
            if (bShowDetail)
 | 
			
		||||
                global.ToLog("WAS CALC: " + Num + " SumHash: " + global.GetHexFromArr(Block.SumHash).substr(0, 12));
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (Num > 0) {
 | 
			
		||||
            var Block0 = global.SERVER.ReadBlockDB(Num - 1);
 | 
			
		||||
            if (Block0) {
 | 
			
		||||
                var Item0 = BlockTree.LoadValue(Block0.BlockNum, 1);
 | 
			
		||||
                if (Item0 && global.CompareArr(Item0.SumHash, Block0.SumHash) !== 0) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        global.SERVER.BlockProcessTX(Block);
 | 
			
		||||
        if (Num % 100000 === 0)
 | 
			
		||||
            global.ToLog("CALC: " + Num);
 | 
			
		||||
        CountTX++;
 | 
			
		||||
        if (bShowDetail)
 | 
			
		||||
            global.ToLog("    CALC: " + Num + " SumHash: " + global.GetHexFromArr(Block.SumHash).substr(0, 12));
 | 
			
		||||
        BlockTree.SaveValue(Block.BlockNum, { BlockNum: Block.BlockNum, SumHash: Block.SumHash });
 | 
			
		||||
        LastBlockNum = Block.BlockNum;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function FindMinimal() {
 | 
			
		||||
    var MaxNumBlockDB = global.SERVER.GetMaxNumBlockDB();
 | 
			
		||||
    if (MaxNumBlockDB && MaxNumBlockDB < LastBlockNum) {
 | 
			
		||||
        if (bShowDetail)
 | 
			
		||||
            global.ToLog("MaxNumBlockDB<LastBlockNum: " + MaxNumBlockDB + "<" + LastBlockNum);
 | 
			
		||||
        LastBlockNum = MaxNumBlockDB - 1;
 | 
			
		||||
        BlockTree.Clear();
 | 
			
		||||
    }
 | 
			
		||||
    if (LastBlockNum < MinimalValidBlock)
 | 
			
		||||
        LastBlockNum = MinimalValidBlock;
 | 
			
		||||
    if (bShowDetail)
 | 
			
		||||
        global.ToLog("FindMinimal from LastBlockNum=" + LastBlockNum);
 | 
			
		||||
    for (var Num = LastBlockNum; Num--; Num >= 0) {
 | 
			
		||||
        if (Num < MinimalValidBlock)
 | 
			
		||||
            break;
 | 
			
		||||
        var Block = global.SERVER.ReadBlockHeaderDB(Num);
 | 
			
		||||
        if (!Block) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (!IsValidSumHash(Block)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (Block.BlockNum % PERIOD_ACCOUNT_HASH === 0) {
 | 
			
		||||
            var Item = global.DApps.Accounts.GetAccountHashItem(Block.BlockNum);
 | 
			
		||||
            if (Item) {
 | 
			
		||||
                BlockTree.SaveValue(Block.BlockNum, Item);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        var Item = BlockTree.LoadValue(Block.BlockNum, 1);
 | 
			
		||||
        if (Item && global.CompareArr(Item.SumHash, Block.SumHash) === 0)
 | 
			
		||||
            return Block;
 | 
			
		||||
        if (bShowDetail)
 | 
			
		||||
            global.ToLog("" + Num + "  " + Block.BlockNum + ". Item=" + JSON.stringify(Item) + "  MinimalValidBlock=" + MinimalValidBlock);
 | 
			
		||||
    }
 | 
			
		||||
    if (bShowDetail)
 | 
			
		||||
        global.ToLog("MinimalValidBlock:" + MinimalValidBlock);
 | 
			
		||||
    if (MinimalValidBlock === 0 && LastBlockNum > 0) {
 | 
			
		||||
        RewriteAllTransactions();
 | 
			
		||||
    }
 | 
			
		||||
    Block = global.SERVER.ReadBlockHeaderDB(MinimalValidBlock);
 | 
			
		||||
    return Block;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function IsValidSumHash(Block) {
 | 
			
		||||
    if (Block.BlockNum <= MinimalValidBlock + global.BLOCK_PROCESSING_LENGTH2)
 | 
			
		||||
        return 1;
 | 
			
		||||
    if (Block.BlockNum < 16)
 | 
			
		||||
        return 1;
 | 
			
		||||
    if (IsZeroArr(Block.SumHash))
 | 
			
		||||
        return 0;
 | 
			
		||||
    var PrevBlock = global.SERVER.ReadBlockHeaderDB(Block.BlockNum - 1);
 | 
			
		||||
    if (!PrevBlock)
 | 
			
		||||
        return 0;
 | 
			
		||||
    var SumHash2 = shaarr2(PrevBlock.SumHash, Block.Hash);
 | 
			
		||||
    if (global.CompareArr(SumHash2, Block.SumHash) === 0)
 | 
			
		||||
        return 1;
 | 
			
		||||
    return 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function InitTXProcess() {
 | 
			
		||||
    var StateTX = global.DApps.Accounts.DBStateTX.Read(0);
 | 
			
		||||
    if (!StateTX) {
 | 
			
		||||
        LastBlockNum = 0;
 | 
			
		||||
        var MaxNum = global.DApps.Accounts.DBAccountsHash.GetMaxNum();
 | 
			
		||||
        if (MaxNum > 0) {
 | 
			
		||||
            var Item = global.DApps.Accounts.DBAccountsHash.Read(MaxNum);
 | 
			
		||||
            if (Item) {
 | 
			
		||||
                LastBlockNum = Item.BlockNum;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        global.ToLog("DETECT NEW VER on BlockNum=" + LastBlockNum, 2);
 | 
			
		||||
        global.DApps.Accounts.DBStateTX.Write({ Num: 0, BlockNum: LastBlockNum, BlockNumMin: MinimalValidBlock });
 | 
			
		||||
    }
 | 
			
		||||
    StateTX = global.DApps.Accounts.DBStateTX.Read(0);
 | 
			
		||||
    LastBlockNum = StateTX.BlockNum;
 | 
			
		||||
    MinimalValidBlock = StateTX.BlockNumMin;
 | 
			
		||||
    LastBlockNum = PERIOD_ACCOUNT_HASH * Math.trunc(LastBlockNum / PERIOD_ACCOUNT_HASH);
 | 
			
		||||
    if (LastBlockNum > 100) {
 | 
			
		||||
        LastBlockNum = 1 + LastBlockNum - 100;
 | 
			
		||||
    }
 | 
			
		||||
    global.DApps.Accounts.CalcMerkleTree(1);
 | 
			
		||||
    if (LastBlockNum <= 0)
 | 
			
		||||
        RewriteAllTransactions();
 | 
			
		||||
    else
 | 
			
		||||
        global.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) {
 | 
			
		||||
        global.ToLog("*************Cant run RewriteAllTransactions, MinimalValidBlock:" + MinimalValidBlock, 2);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    global.ToLog("*************RewriteAllTransactions");
 | 
			
		||||
    for (var key in DApps) {
 | 
			
		||||
        DApps[key].ClearDataBase();
 | 
			
		||||
    }
 | 
			
		||||
    LastBlockNum = 0;
 | 
			
		||||
    BlockTree.Clear();
 | 
			
		||||
    global.ToLog("Start num = " + LastBlockNum, 2);
 | 
			
		||||
};
 | 
			
		||||
global.ReWriteDAppTransactions = ReWriteDAppTransactions;
 | 
			
		||||
 | 
			
		||||
function ReWriteDAppTransactions(Params) {
 | 
			
		||||
    var StartNum = Params.StartNum;
 | 
			
		||||
    var EndNum = Params.EndNum;
 | 
			
		||||
    global.ToLog("ReWriteDAppTransactions: " + StartNum + " - " + EndNum);
 | 
			
		||||
    BlockTree.Clear();
 | 
			
		||||
    if (StartNum < LastBlockNum)
 | 
			
		||||
        LastBlockNum = StartNum;
 | 
			
		||||
    global.ToLog("Start num = " + LastBlockNum, 2);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function TXPrepareLoadRest(BlockNum) {
 | 
			
		||||
    StopTxProcess = 1;
 | 
			
		||||
    MinimalValidBlock = BlockNum;
 | 
			
		||||
    global.ToLog("*************TXPrepareLoadRest:" + BlockNum, 2);
 | 
			
		||||
    for (var key in DApps) {
 | 
			
		||||
        DApps[key].ClearDataBase();
 | 
			
		||||
    }
 | 
			
		||||
    LastBlockNum = BlockNum;
 | 
			
		||||
    BlockTree.Clear();
 | 
			
		||||
    global.DApps.Accounts.DBStateTX.Write({ Num: 0, BlockNum: LastBlockNum, BlockNumMin: LastBlockNum });
 | 
			
		||||
};
 | 
			
		||||
global.TXPrepareLoadRest = TXPrepareLoadRest;
 | 
			
		||||
 | 
			
		||||
function TXWriteAccArr(Params) {
 | 
			
		||||
    var WorkStruct = {};
 | 
			
		||||
    var WorkFormat = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
 | 
			
		||||
    global.ToLog("Write accounts: " + Params.StartNum + "-" + Params.Arr.length, 2);
 | 
			
		||||
    for (var i = 0; i < Params.Arr.length; i++) {
 | 
			
		||||
        var Data = global.BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct);
 | 
			
		||||
        Data.Num = Params.StartNum + i;
 | 
			
		||||
        global.DApps.Accounts._DBStateWrite(Data, MinimalValidBlock);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
global.TXWriteAccArr = TXWriteAccArr;
 | 
			
		||||
 | 
			
		||||
function TXWriteSmartArr(Params) {
 | 
			
		||||
    var WorkStruct = {};
 | 
			
		||||
    var WorkFormat = global.DApps.Smart.FORMAT_ROW;
 | 
			
		||||
    global.ToLog("Write smarts: " + Params.StartNum + "-" + Params.Arr.length, 2);
 | 
			
		||||
    for (var i = 0; i < Params.Arr.length; i++) {
 | 
			
		||||
        var Data = global.BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct);
 | 
			
		||||
        Data.Num = Params.StartNum + i;
 | 
			
		||||
        global.DApps.Smart.DBSmart.Write(Data);
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
global.TXWriteSmartArr = TXWriteSmartArr;
 | 
			
		||||
 | 
			
		||||
function TXWriteAccHash() {
 | 
			
		||||
    StopTxProcess = 0;
 | 
			
		||||
    global.ToLog("Start TXWriteAccHash: " + MinimalValidBlock, 2);
 | 
			
		||||
    for (var num = 0; true; num++) {
 | 
			
		||||
        var Item = global.DApps.Smart.DBSmart.Read(num);
 | 
			
		||||
        if (!Item)
 | 
			
		||||
            break;
 | 
			
		||||
        var Body = global.BufLib.GetBufferFromObject(Item, global.DApps.Smart.FORMAT_ROW, 20000, {});
 | 
			
		||||
        global.DApps.Smart.DBSmartWrite(Item);
 | 
			
		||||
    }
 | 
			
		||||
    global.DApps.Accounts.CalcMerkleTree(1);
 | 
			
		||||
    var Block = { BlockNum: MinimalValidBlock, SumHash: [] };
 | 
			
		||||
    var MaxAccount = global.DApps.Accounts.GetMaxAccount();
 | 
			
		||||
    var DataHash = global.DApps.Accounts.CalcHash(Block, MaxAccount);
 | 
			
		||||
    return DataHash;
 | 
			
		||||
};
 | 
			
		||||
global.TXWriteAccHash = TXWriteAccHash;
 | 
			
		||||
global.EvalCode = function(Code) {
 | 
			
		||||
    var Result;
 | 
			
		||||
    try {
 | 
			
		||||
        var ret = eval(Code);
 | 
			
		||||
        Result = JSON.stringify(ret, "", 4);
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) {
 | 
			
		||||
        Result = "" + e;
 | 
			
		||||
    }
 | 
			
		||||
    return Result;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										864
									
								
								src/process/web-process.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										864
									
								
								src/process/web-process.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,864 @@
 | 
			
		||||
/*
 | 
			
		||||
 * @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
 | 
			
		||||
*/
 | 
			
		||||
import * as crypto from 'crypto'
 | 
			
		||||
import * as http from 'http'
 | 
			
		||||
import * as net from 'net'
 | 
			
		||||
import * as url from 'url'
 | 
			
		||||
import * as fs from 'fs'
 | 
			
		||||
import * as querystring from 'querystring'
 | 
			
		||||
 | 
			
		||||
global.PROCESS_NAME = "WEB";
 | 
			
		||||
import '../core/constant'
 | 
			
		||||
global.MAX_STAT_PERIOD = 600;
 | 
			
		||||
global.DATA_PATH = global.GetNormalPathString(global.DATA_PATH);
 | 
			
		||||
global.CODE_PATH = global.GetNormalPathString(global.CODE_PATH);
 | 
			
		||||
import "../core/library"
 | 
			
		||||
import "../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) {
 | 
			
		||||
    let {
 | 
			
		||||
        GlobalRunMap,
 | 
			
		||||
        ADD_TO_STAT,
 | 
			
		||||
        ToLogClient0,
 | 
			
		||||
        ArrLogClient
 | 
			
		||||
    } = global
 | 
			
		||||
    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;
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
var RedirectServer;
 | 
			
		||||
var HostingServer;
 | 
			
		||||
 | 
			
		||||
let {
 | 
			
		||||
    ToLogWeb,
 | 
			
		||||
    CHECK_STOP_CHILD_PROCESS,
 | 
			
		||||
    ToError,
 | 
			
		||||
    ToLog,
 | 
			
		||||
    TO_ERROR_LOG,
 | 
			
		||||
    PrepareStatEverySecond,
 | 
			
		||||
    ToLogTrace
 | 
			
		||||
} = global
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
    global.ToError(err.stack);
 | 
			
		||||
    global.ToLog(err.stack);
 | 
			
		||||
    TO_ERROR_LOG("HOSTING", 777, err);
 | 
			
		||||
    global.ToLog("-----------------HOSTING EXIT------------------", 0);
 | 
			
		||||
    process.exit();
 | 
			
		||||
});
 | 
			
		||||
process.on('error' as any, function(err: TeraError) {
 | 
			
		||||
    global.ToError("HOSTING:\n" + err.stack);
 | 
			
		||||
    global.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";
 | 
			
		||||
let {
 | 
			
		||||
    GetDataPath,
 | 
			
		||||
    CheckCreateDir,
 | 
			
		||||
    LoadParams,
 | 
			
		||||
    SaveParams,
 | 
			
		||||
    ADD_TO_STAT
 | 
			
		||||
} = global
 | 
			
		||||
if (global.HTTPS_HOSTING_DOMAIN) {
 | 
			
		||||
    var file_sert = global.GetDataPath("sertif.lst");
 | 
			
		||||
    CheckCreateDir(global.GetDataPath("tmp"));
 | 
			
		||||
    var greenlock = require('greenlock').create({
 | 
			
		||||
        version: 'draft-12', server: 'https://acme-v02.api.letsencrypt.org/directory', configDir: global.GetDataPath('tmp'),
 | 
			
		||||
    });
 | 
			
		||||
    var redir = require('redirect-https')();
 | 
			
		||||
    RedirectServer = require('http').createServer(greenlock.middleware(redir));
 | 
			
		||||
    RedirectServer.on('error', function(err) {
 | 
			
		||||
        global.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) {
 | 
			
		||||
            global.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) {
 | 
			
		||||
        global.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) {
 | 
			
		||||
            global.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);
 | 
			
		||||
    ADD_TO_STAT("HTTP_ALL");
 | 
			
		||||
    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;
 | 
			
		||||
                global.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() {
 | 
			
		||||
    let {
 | 
			
		||||
        ToLogClient,
 | 
			
		||||
        LISTEN_IP
 | 
			
		||||
    } = global
 | 
			
		||||
    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;
 | 
			
		||||
        }
 | 
			
		||||
        global.ToError("H##6");
 | 
			
		||||
        global.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 = global.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 = {};
 | 
			
		||||
let HostingCaller: HostingCaller = {}
 | 
			
		||||
global.HostingCaller = HostingCaller;
 | 
			
		||||
function DoCommandNew(response, Type, Path, Params) {
 | 
			
		||||
    if (Path.substring(0, 1) === "/")
 | 
			
		||||
        Path = Path.substring(1);
 | 
			
		||||
    var ArrPath = Path.split('/', 5);
 | 
			
		||||
    var Caller = global.HostingCaller;
 | 
			
		||||
    var Method = ArrPath[0];
 | 
			
		||||
    if (ArrPath[0] === "api") {
 | 
			
		||||
        if (ArrPath[1] === "v2") {
 | 
			
		||||
            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);
 | 
			
		||||
    var F = Caller[Method];
 | 
			
		||||
    if (F) {
 | 
			
		||||
        response.writeHead(200, { 'Content-Type': 'text/plain', 'Access-Control-Allow-Origin': "*" });
 | 
			
		||||
        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) {
 | 
			
		||||
            global.ToLog("ERR PATH:" + Path);
 | 
			
		||||
            global.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;
 | 
			
		||||
                    global.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) {
 | 
			
		||||
    var MaxNumBlockDB = global.SERVER.GetMaxNumBlockDB();
 | 
			
		||||
    var Ret: any = {
 | 
			
		||||
        result: 1, VersionNum: global.UPDATE_CODE_VERSION_NUM, NETWORK: global.NETWORK, MaxNumBlockDB: MaxNumBlockDB, CurBlockNum: global.GetCurrentBlockNumByTime(),
 | 
			
		||||
        MaxAccID: global.DApps.Accounts.GetMaxAccount(), MaxDappsID: global.DApps.Smart.GetMaxNum(), CurTime: Date.now(), DELTA_CURRENT_TIME: global.DELTA_CURRENT_TIME,
 | 
			
		||||
        MIN_POWER_POW_TR: global.MIN_POWER_POW_TR, FIRST_TIME_BLOCK: global.FIRST_TIME_BLOCK, CONSENSUS_PERIOD_TIME: global.CONSENSUS_PERIOD_TIME, NEW_SIGN_TIME: global.NEW_SIGN_TIME,
 | 
			
		||||
        PRICE_DAO: global.PRICE_DAO(MaxNumBlockDB),
 | 
			
		||||
    };
 | 
			
		||||
    if (typeof Params === "object" && Params.Diagram == 1) {
 | 
			
		||||
        var arrNames = ["MAX:ALL_NODES", "MAX:HASH_RATE_B"];
 | 
			
		||||
        Ret.arr = global.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 < global.ArrLogClient.length; i++) {
 | 
			
		||||
            var Item = global.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 = global.DApps.Accounts.GetRowsAccounts(ParseNum(Params.StartNum), ParseNum(Params.CountNum));
 | 
			
		||||
    return { result: 1, arr: arr };
 | 
			
		||||
};
 | 
			
		||||
HostingCaller.GetAccount = function(id) {
 | 
			
		||||
    id = ParseNum(id);
 | 
			
		||||
    var arr = global.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 = global.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 = global.random(List.length);
 | 
			
		||||
            Item = List[num];
 | 
			
		||||
            if (mapWasAdd[Item.ip]) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            mapWasAdd[Item.ip] = 1;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            Item = List[i];
 | 
			
		||||
        }
 | 
			
		||||
        var Value: any = { ip: Item.ip, port: Item.portweb, };
 | 
			
		||||
        if (Geo) {
 | 
			
		||||
            if (!Item.Geo)
 | 
			
		||||
                global.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: [] };
 | 
			
		||||
    var Accounts = global.DApps.Accounts;
 | 
			
		||||
    for (var num = LastMaxNum; true; num++) {
 | 
			
		||||
        if (Accounts.IsHole(num))
 | 
			
		||||
            continue;
 | 
			
		||||
        var Data = Accounts.ReadState(num);
 | 
			
		||||
        if (!Data)
 | 
			
		||||
            break;
 | 
			
		||||
        var StrKey = global.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 = global.GetHexFromArr(Data.PubKey);
 | 
			
		||||
        if (Data.Currency)
 | 
			
		||||
            Data.CurrencyObj = global.DApps.Smart.ReadSimple(Data.Currency);
 | 
			
		||||
        if (Data.Value.Smart) {
 | 
			
		||||
            Data.SmartObj = global.DApps.Smart.ReadSimple(Data.Value.Smart);
 | 
			
		||||
            try {
 | 
			
		||||
                Data.SmartState = global.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 = global.DApps.Smart.GetMaxNum();
 | 
			
		||||
    if (MaxNumNow !== CategoryDappMaxNumWas) {
 | 
			
		||||
        for (var Num = CategoryDappMaxNumWas; Num <= MaxNumNow; Num++) {
 | 
			
		||||
            var Item = global.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 = global.GetCurrentBlockNumByTime();
 | 
			
		||||
    Ret.BlockNumDB = global.SERVER.BlockNumDB;
 | 
			
		||||
    Ret.MaxAccID = global.DApps.Accounts.GetMaxAccount();
 | 
			
		||||
    Ret.MaxDappsID = global.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 = global.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 = global.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 = global.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) {
 | 
			
		||||
        global.GlobalRunID++;
 | 
			
		||||
        try {
 | 
			
		||||
            process.send({ cmd: "call", id: global.GlobalRunID, Name: Name, Params: Params });
 | 
			
		||||
            global.GlobalRunMap[global.GlobalRunID] = F;
 | 
			
		||||
        }
 | 
			
		||||
        catch (e) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        process.send({ cmd: "call", id: 0, Name: Name, Params: Params });
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
setInterval(function() {
 | 
			
		||||
    if (global.SERVER)
 | 
			
		||||
        global.SERVER.Close();
 | 
			
		||||
    global.DApps.Accounts.Close();
 | 
			
		||||
    global.DApps.Smart.DBSmart.Close();
 | 
			
		||||
}, 500);
 | 
			
		||||
setInterval(function() {
 | 
			
		||||
    var MaxNumBlockDB = global.SERVER.GetMaxNumBlockDB();
 | 
			
		||||
    var HASHARATE_BLOCK_LENGTH = 10;
 | 
			
		||||
    var arr = global.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 = global.SERVER.BlockChainToBuf(StartNum, StartNum, MaxNumBlockDB);
 | 
			
		||||
    }
 | 
			
		||||
}, 700);
 | 
			
		||||
require("./api-exchange.js");
 | 
			
		||||
try {
 | 
			
		||||
    require("../SITE/JS/web-addon.js");
 | 
			
		||||
}
 | 
			
		||||
catch (e) {
 | 
			
		||||
}
 | 
			
		||||
global.LoadBlockFromNetwork = function(Params, F) {
 | 
			
		||||
    global.ToLog("RUN: LoadBlockFromNetwork:" + Params.BlockNum, 2);
 | 
			
		||||
    process.RunRPC("LoadBlockFromNetwork", { BlockNum: Params.BlockNum, F: 1 }, function(Err, Block) {
 | 
			
		||||
        global.ToLog("RETURN: LoadBlockFromNetwork: " + Params.BlockNum, 2);
 | 
			
		||||
        F(Err, Block);
 | 
			
		||||
    });
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user