/* * @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" import "./child-process" global.READ_ONLY_DB = 1; global.MAX_STAT_PERIOD = 600; var HostNodeList = []; var AllNodeList = []; var NodeBlockChain = []; process.on('message', function(msg) { switch (msg.cmd) { case "retcall": var F = global.GlobalRunMap[msg.id]; if (F) { delete global.GlobalRunMap[msg.id]; F(msg.Err, msg.Params); } break; case "Stat": global.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": { global.AddDappEventToGlobalMap(msg.Data); break; } case "ToLogClient": { global.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; } } global.ArrLogClient.push({ text: msg.ResultStr, key: msg.TX, final: msg.bFinal, }); break; } } }); var RedirectServer; var HostingServer; global.OnExit = function() { if (RedirectServer) RedirectServer.close(); if (HostingServer) HostingServer.close(); }; if (!global.HTTP_HOSTING_PORT) { global.ToLogTrace("global.HTTP_HOSTING_PORT=" + global.HTTP_HOSTING_PORT); global.OnExit(); 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(global.PrepareStatEverySecond, 1000); var IndexName = "index.html"; if (global.HTTPS_HOSTING_DOMAIN && global.HTTP_HOSTING_PORT === 443) { var file_sert = global.GetDataPath("sertif.lst"); global.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 = global.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) { global.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; global.SetSafeResponce(response); var DataURL = url.parse(request.url); var Params = querystring.parse(DataURL.query); var Path = querystring.unescape(DataURL.pathname); global.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() { HostingServer.on('error', function(err) { if (err.code === 'EADDRINUSE') { TimeToRerun = Math.floor(TimeToRerun * 1.1); if (TimeToRerun > 1000000 * 1000) return; global.ToLogClient('Port ' + global.HTTP_HOSTING_PORT + ' in use, retrying...'); if (HostingServer.Server) HostingServer.Server.close(); if (!bWasRun) setTimeout(function() { if (!bWasRun) RunListenServer(); }, TimeToRerun); return; } global.ToError("H##6"); global.ToError(err); }); global.ToLog("Prepare to run WEB-server on port: " + global.HTTP_HOSTING_PORT); HostingServer.listen(global.HTTP_HOSTING_PORT, global.LISTEN_IP, function() { if (!bWasRun) global.ToLog("Run WEB-server on " + global.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 = global.WebApi2; } Method = ArrPath[2]; } global.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": global.SendBlockFile(response, ArrPath[1], ArrPath[2]); break; case "DappTemplateFile": global.DappTemplateFile(response, ArrPath[1]); break; case "smart": global.DappSmartCodeFile(response, ArrPath[1]); break; case "client": global.DappClientCodeFile(response, ArrPath[1]); break; default: { var Name = ArrPath[ArrPath.length - 1]; if (typeof Name !== "string") Name = "ErrorPath"; else if (Name.indexOf("..") >= 0 || Name.indexOf("\\") >= 0 || Name.indexOf("/") >= 0) Name = "ErrorFilePath"; if (Name === "" || 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; } global.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(global.ParseNum(Params.StartNum), global.ParseNum(Params.CountNum)); return { result: 1, arr: arr }; }; HostingCaller.GetAccount = function(id) { id = global.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 = global.ParseNum(Params.StartNum); Params.CountNum = global.ParseNum(Params.CountNum); if (Params.CountNum > MaxCountViewRows) Params.CountNum = MaxCountViewRows; if (!Params.CountNum) Params.CountNum = 1; return global.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 = global.ParseNum(Params.Param3); Params.StartNum = global.ParseNum(Params.StartNum); Params.CountNum = global.ParseNum(Params.CountNum); if (Params.CountNum > MaxCountViewRows) Params.CountNum = MaxCountViewRows; return global.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(global.ParseNum(Params.StartNum), global.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, aaa, bbb, 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 = global.GetUserContext(Params); var StrInfo = JSON.stringify(Ret); if (Params.AllData === "0") Params.AllData = 0; 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 global.HTTPCaller.DappSmartHTMLFile(Params); }; HostingCaller.DappBlockFile = function(Params, responce) { if (typeof Params !== "object") return { result: 0 }; return global.HTTPCaller.DappBlockFile(Params, responce); }; HostingCaller.DappInfo = function(Params) { if (typeof Params !== "object") return { result: 0 }; var SmartNum = global.ParseNum(Params.Smart); process.send({ cmd: "SetSmartEvent", Smart: SmartNum }); var Context = global.GetUserContext(Params); var Ret = global.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, undefined, 1); var Smart = global.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; }; global.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(global.ParseNum(Params.StartNum), global.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(global.ParseNum(Params.StartNum), global.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 = global.ParseNum(Params.StartNum); Params.CountNum = global.ParseNum(Params.CountNum); if (Params.CountNum > MaxCountViewRows) Params.CountNum = MaxCountViewRows; if (!Params.CountNum) Params.CountNum = 1; return global.HTTPCaller.DappBlockList(Params, response); }; HostingCaller.DappTransactionList = function(Params, response) { if (typeof Params !== "object") return { result: 0 }; Params.BlockNum = global.ParseNum(Params.BlockNum); Params.StartNum = global.ParseNum(Params.StartNum); Params.CountNum = global.ParseNum(Params.CountNum); if (Params.CountNum > MaxCountViewRows) Params.CountNum = MaxCountViewRows; if (!Params.CountNum) Params.CountNum = 1; return global.HTTPCaller.DappTransactionList(Params, response); }; HostingCaller.DappStaticCall = function(Params, response) { if (typeof Params !== "object") return { result: 0 }; return global.HTTPCaller.DappStaticCall(Params, response); }; HostingCaller.GetHistoryTransactions = function(Params) { if (typeof Params !== "object") return { result: 0 }; return global.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; }; 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; global.ADD_TO_STAT("MAX:HASH_RATE_B", AvgPow); } var Count = global.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); }); };