/* * @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 */ "use strict"; import CNode from './node' import * as crypto from 'crypto' import { secp256k1 } from './library' global.PERIOD_FOR_RECONNECT = 3600 * 1000; global.CHECK_DELTA_TIME = { Num: 0, bUse: 0, StartBlockNum: 0, EndBlockNum: 0, bAddTime: 0, DeltaTime: 0, Sign: [] }; global.CHECK_POINT = { BlockNum: 0, Hash: [], Sign: [] }; global.CODE_VERSION = { BlockNum: 0, addrArr: [], LevelUpdate: 0, BlockPeriod: 0, VersionNum: global.UPDATE_CODE_VERSION_NUM, Hash: [], Sign: [], StartLoadVersionNum: 0 }; global.NET_CONSTANT = { Num: 0, BlockNum: 0, MaxTrasactionLimit: global.MAX_TRANSACTION_LIMIT, Reserv1: 0, Reserv2: 0, Reserv3: 0, Reserv4: 0, Reserv5: 0, Hash: [], Sign: [] }; global.START_LOAD_CODE = {}; const MAX_PERIOD_GETNODES = 120 * 1000; global.MIN_PERIOD_PING = 4 * 1000; const MAX_PERIOD_PING = 120 * 1000; global.MAX_PING_FOR_CONNECT = 400; var MAX_TIME_CORRECT = 3 * 3600 * 1000; global.MAX_WAIT_PERIOD_FOR_HOT = 4 * global.CONSENSUS_PERIOD_TIME; const PERIOD_FOR_START_CHECK_TIME = 300; const CAN_START_TIME_AVG = 200; import CMessages from './transfer-msg' export default class CConnect extends CMessages { ip port StartTime WasNodesSort LevelNodes NodesArr NodesArrUnSort NodesMap NodesIPMap PerioadAfterCanStart КодДляРазработчикаХекс CommonKey KeyToNode NameToNode BlockNumDB idTimerSetConst SignCurrentTimeDev StopDetectGrayMode LastNotZeroNodesTime TransferTree СтатБлок BusyLevel SendTrafficFree constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) { super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) this.StartTime = Date.now() this.WasNodesSort = false this.LevelNodes = [] this.NodesArr = [] this.NodesArrUnSort = [] this.NodesMap = {} this.NodesIPMap = {} this.WasNodesSort = true this.PerioadAfterCanStart = 0 this.КодДляРазработчикаХекс = global.GetHexFromArr(this.KeyPair.computeSecret(global.DEVELOP_PUB_KEY, null)) this.DO_CONSTANT() if (!global.ADDRLIST_MODE && !this.VirtualMode) { setInterval(this.StartPingPong.bind(this), 1000) setInterval(this.DeleteBadConnectingByTimer.bind(this), global.MAX_WAIT_PERIOD_FOR_STATUS / 2) setInterval(this.StartCheckTransferTree.bind(this), 1000) } setInterval(this.NodesArrSort.bind(this), 30000) } DO_CONSTANT() { this.CommonKey = global.GetHexFromArr(global.WALLET.HashProtect(global.COMMON_KEY)) this.KeyToNode = global.shaarr(global.COMMON_KEY) this.NameToNode = this.ValueToXOR("Name", global.NODES_NAME) } СтатДанныеОтладкиИзБлока() { var Массив = []; if (this.СтатБлок && this.СтатБлок.SeqHash) { global.WriteArrToArr(Массив, this.ValueToXORDevelop("Stat:BlockNum", this.СтатБлок.BlockNum, "uint"), 6) global.WriteArrToArr(Массив, this.ValueToXORDevelop("Stat:SeqHash", this.СтатБлок.SeqHash, "hash"), 32) global.WriteArrToArr(Массив, this.ValueToXORDevelop("Stat:AddrHash", this.СтатБлок.AddrHash, "hash"), 32) } return Массив; } ДоступенКлючРазработчика(Node) { if (Node.PubKey && global.WALLET.WalletOpen !== false && global.IsDeveloperAccount(global.WALLET.PubKeyArr)) { return 1; } return 0; } БлокИзДанных(Node, Arr) { var Block: any = {}; if (this.ДоступенКлючРазработчика(Node) && !global.IsZeroArr(Arr)) { var Data = global.BufLib.GetObjectFromBuffer(Arr, "{BlockNum:arr6,SeqHash:arr32,AddrHash:arr32}", {}); Block.BlockNum = this.ValueFromXORDevelop(Node, "Stat:BlockNum", Data.BlockNum, "uint") Block.SeqHash = this.ValueFromXORDevelop(Node, "Stat:SeqHash", Data.SeqHash, "hash") Block.AddrHash = this.ValueFromXORDevelop(Node, "Stat:AddrHash", Data.AddrHash, "hash") } return Block; } StartConnectTry(Node) { var Delta = Date.now() - Node.StartTimeConnect; if (Delta >= Node.NextConnectDelta && this.IsCanConnect(Node)) { if (!global.GetSocketStatus(Node.Socket)) { Node.StartTimeConnect = Date.now() if (Delta < 60 * 1000) Node.NextConnectDelta = Node.NextConnectDelta * 2 else Node.NextConnectDelta = Math.trunc(Node.NextConnectDelta * 1.2) Node.CreateConnect() } } } FindRunNodeContext(addrArr, ip, port, bUpdate) { var Node, addrStr; addrStr = global.GetHexFromAddres(addrArr) Node = this.NodesMap[addrStr] if (!Node) { var key = "" + ip + ":" + port; Node = this.NodesIPMap[key] if (!Node) { Node = this.GetNewNode(ip, port, addrStr) } } if (Node.addrStr !== addrStr) { delete this.NodesMap[Node.addrStr] this.NodesMap[addrStr] = Node Node.addrStrTemp = undefined } Node.addrArr = addrArr Node.addrStr = addrStr Node.ip = ip.trim() Node.port = port return Node; } CheckNodeMap(Node) { if (Node.addrStrTemp && Node.addrStrTemp !== Node.addrStr) { delete this.NodesMap[Node.addrStrTemp] var Node2 = this.NodesMap[Node.addrStr]; if (Node2 && Node2 !== Node) { Node2.Delete = 1 global.AddNodeInfo(Node2, "FIND DOUBLE!!") delete this.NodesMap[Node.addrStr] } this.NodesMap[Node.addrStr] = Node Node.addrStrTemp = undefined } } StartHandshake(Node) { return this.StartConnectTry(Node); } StartPingPong() { if (global.glStopNode) return; if (global.CAN_START) this.PerioadAfterCanStart++ this.TimeDevCorrect() var arr = global.SERVER.GetActualNodes(); for (var i = 0; i < arr.length; i++) { var Node = arr[i]; if (this.IsCanConnect(Node) && !Node.IsAddrList) { if (Node.Hot) Node.NextPing = global.MIN_PERIOD_PING if (Node.NextPing < global.MIN_PERIOD_PING) Node.NextPing = global.MIN_PERIOD_PING var Delta = Date.now() - Node.PingStart; if (Delta >= Node.NextPing) { Node.PingStart = Date.now() Node.NextPing = Node.NextPing * 1.5 if (Node.NextPing > MAX_PERIOD_PING) Node.NextPing = MAX_PERIOD_PING if (!Node.PingNumber) Node.PingNumber = 0 Node.PingNumber++ var Context = { "StartTime": global.GetCurrentTime(0), PingNumber: Node.PingNumber }; this.SendF(Node, { "Method": "PING", "Context": Context, "Data": this.GetPingData(Node) }) } } } } GetPingData(Node) { var GrayAddres = 0; if (global.GrayConnect()) GrayAddres = 1 var BlockNumHash = Math.trunc((global.GetCurrentBlockNumByTime() - global.BLOCK_PROCESSING_LENGTH2) / global.PERIOD_ACCOUNT_HASH) * global.PERIOD_ACCOUNT_HASH; var AccountsHash = global.DApps.Accounts.GetHashOrUndefined(BlockNumHash); var CheckPointHashDB = []; if (global.CHECK_POINT.BlockNum && global.CHECK_POINT.BlockNum <= this.BlockNumDB) { var Block = this.ReadBlockHeaderFromMapDB(global.CHECK_POINT.BlockNum); if (Block) { CheckPointHashDB = Block.Hash } } var HashDB = []; if (this.BlockNumDB > 0) { var Block = this.ReadBlockHeaderFromMapDB(this.BlockNumDB); if (Block) HashDB = Block.Hash } var LevelCount = this.GetLevelEnum(Node); var StopGetBlock = global.STOPGETBLOCK; if (!StopGetBlock && this.BusyLevel) { if (Node.BlockProcessCount <= this.BusyLevel) StopGetBlock = 1 } var СтатДанные = []; var DirectMAccount = 0; var Ret = { VERSIONMAX: global.DEF_VERSION, FIRST_TIME_BLOCK: 0, PingVersion: 3, GrayConnect: GrayAddres, Reserve2: 0, AutoCorrectTime: global.AUTO_CORRECT_TIME, LevelCount: LevelCount, Time: (global.GetCurrentTime() - 0), BlockNumDB: this.BlockNumDB, LoadHistoryMode: this.LoadHistoryMode, CanStart: global.CAN_START, CheckPoint: global.CHECK_POINT, Reserv3: [], Key: this.KeyToNode, Name: this.NameToNode, TrafficFree: this.SendTrafficFree, AccountBlockNum: BlockNumHash, AccountsHash: AccountsHash, MemoryUsage: Math.trunc(process.memoryUsage().heapTotal / 1024 / 1024), CheckDeltaTime: global.CHECK_DELTA_TIME, CodeVersion: global.CODE_VERSION, IsAddrList: global.ADDRLIST_MODE, CheckPointHashDB: CheckPointHashDB, PortWeb: global.HTTP_HOSTING_PORT, HashDB: HashDB, StopGetBlock: StopGetBlock, NetConstant: global.NET_CONSTANT, }; return Ret; } static PING_F(bSend) { return "{\ VERSIONMAX:str15,\ PingVersion:byte,\ GrayConnect:byte,\ Reserve2:byte,\ AutoCorrectTime:byte,\ LevelCount:uint16,\ Time:uint,\ BlockNumDB:uint,\ LoadHistoryMode:byte,\ CanStart:byte,\ CheckPoint:{BlockNum:uint,Hash:hash,Sign:arr64},\ Reserv3:arr38,\ Key:arr32,\ Name:arr32,\ TrafficFree:uint,\ AccountBlockNum:uint,\ AccountsHash:hash,\ MemoryUsage:uint,\ CheckDeltaTime:{Num:uint,bUse:byte,StartBlockNum:uint,EndBlockNum:uint,bAddTime:byte,DeltaTime:uint,Sign:arr64},\ CodeVersion:{BlockNum:uint,addrArr:arr32,LevelUpdate:byte,BlockPeriod:uint,VersionNum:uint,Hash:hash,Sign:arr64},\ IsAddrList:byte,\ CheckPointHashDB:hash,\ PortWeb:uint16,\ HashDB:hash,\ StopGetBlock:uint,\ NetConstant:{Num:uint,BlockNum:uint,MaxTrasactionLimit:uint,Reserv1:uint,Reserv2:uint,Reserv3:uint,Reserv4:uint,Reserv5:uint,Sign:arr64},\ }"; } static PONG_F(bSend) { return CConnect.PING_F(bSend); } PING(Info, CurTime) { this.DoPingData(Info, 1) this.SendF(Info.Node, { "Method": "PONG", "Context": Info.Context, "Data": this.GetPingData(Info.Node) }) } DoPingData(Info, bCheckPoint) { var Node = Info.Node; var Data = this.DataFromF(Info); Info.Node.VERSIONMAX = Data.VERSIONMAX if (Data.PingVersion >= 3 && global.COMMON_KEY && global.CompareArr(Data.Key, this.KeyToNode) === 0) { Node.Name = this.ValueFromXOR(Node, "Name", Data.Name) if (Node.BlockProcessCount < 5000000 + global.TRUST_PROCESS_COUNT) Node.BlockProcessCount = 5000000 + global.TRUST_PROCESS_COUNT } else { Node.Name = "" } Node.INFO = Data Node.INFO.WasPing = 1 Node.LevelCount = Data.LevelCount Node.LoadHistoryMode = Data.LoadHistoryMode Node.LastTime = global.GetCurrentTime() - 0 Node.NextConnectDelta = 1000 Node.StopGetBlock = Data.StopGetBlock Node.portweb = Data.PortWeb if (bCheckPoint) { this.CheckCheckPoint(Data, Info.Node) this.CheckCodeVersion(Data, Info.Node) this.CheckDeltaTime(Data, Info.Node) } } PONG(Info, CurTime) { var Data = this.DataFromF(Info); var Node = Info.Node; if (!Info.Context) return; if (!Info.Context.StartTime) return; if (Info.Context.PingNumber !== Node.PingNumber) return; this.DoPingData(Info, 0) var DeltaTime = global.GetCurrentTime(0) - Info.Context.StartTime; Node.DeltaTimeM = DeltaTime Node.SumDeltaTime += DeltaTime Node.CountDeltaTime++ Node.DeltaTime = Math.trunc(Node.SumDeltaTime / Node.CountDeltaTime) if (!Node.DeltaTime) Node.DeltaTime = 1000 if (DeltaTime) { Node.DeltaGlobTime = global.GetCurrentTime() - (Data.Time + DeltaTime / 2) } this.CheckCheckPoint(Data, Info.Node) if (!global.START_LOAD_CODE.StartLoadVersionNum) global.START_LOAD_CODE.StartLoadVersionNum = 0 this.CheckNetConstant(Data, Info.Node) this.CheckCodeVersion(Data, Info.Node) if (!global.CAN_START) { if (DeltaTime > global.MAX_PING_FOR_CONNECT) { global.ToLog("DeltaTime=" + DeltaTime + ">" + global.MAX_PING_FOR_CONNECT + " ms - " + global.NodeInfo(Node), 2) } } var Times; if (DeltaTime <= global.MAX_PING_FOR_CONNECT) { Times = Node.Times if (!Times || Times.Count >= 10) { Times = { SumDelta: 0, Count: 0, AvgDelta: 0, Arr: [] } Node.Times = Times } var Time1 = Data.Time; var Time2 = global.GetCurrentTime(); var Delta2 = - (Time2 - Time1 - DeltaTime / 2); Times.Arr.push(Delta2) Times.SumDelta += Delta2 Times.Count++ Times.AvgDelta = Times.SumDelta / Times.Count if (Times.Count >= 2) { Times.Arr.sort(function(a, b) { return Math.abs(a) - Math.abs(b); }) Node.AvgDelta = Times.Arr[0] } if (global.AUTO_CORRECT_TIME) { this.CorrectTime() } } else { } global.ADD_TO_STAT("MAX:PING_TIME", DeltaTime) if (!global.CAN_START) { if (Times && Times.Count >= 1 && Times.AvgDelta <= CAN_START_TIME_AVG) { global.ToLog("****************************************** CAN_START") global.CAN_START = true } } this.CheckDeltaTime(Data, Info.Node) } CheckCheckPoint(Data, Node) { if (global.CREATE_ON_START) return; if (Data.CheckPoint.BlockNum && Data.CheckPoint.BlockNum > global.CHECK_POINT.BlockNum) { var SignArr = global.arr2(Data.CheckPoint.Hash, global.GetArrFromValue(Data.CheckPoint.BlockNum)); if (global.CheckDevelopSign(SignArr, Data.CheckPoint.Sign)) { global.CHECK_POINT = Data.CheckPoint this.ResetNextPingAllNode() if (Data.CheckPoint.BlockNum < this.BlockNumDBMin) return; var Block = this.ReadBlockHeaderDB(global.CHECK_POINT.BlockNum); if (Block && global.CompareArr(Block.Hash, global.CHECK_POINT.Hash) !== 0) { this.BlockNumDB = global.CHECK_POINT.BlockNum - 1 this.TruncateBlockDB(this.BlockNumDB) this.StartSyncBlockchain(Node, 0, 1) } } else { Node.NextConnectDelta = 60 * 1000 global.ToLog("Error Sign CheckPoint=" + Data.CheckPoint.BlockNum + " from " + global.NodeInfo(Node)) this.AddCheckErrCount(Node, 10, "Error Sign CheckPoint") } } } CheckDeltaTime(Data, Node) { if (global.AUTO_CORRECT_TIME) if (global.CAN_START && !global.CREATE_ON_START) { if (Data.CheckDeltaTime.Num > global.CHECK_DELTA_TIME.Num) { var SignArr = this.GetSignCheckDeltaTime(Data.CheckDeltaTime); if (global.CheckDevelopSign(SignArr, Data.CheckDeltaTime.Sign)) { global.CHECK_DELTA_TIME = Data.CheckDeltaTime } else { Node.NextConnectDelta = 60 * 1000 global.ToLog("Error Sign CheckDeltaTime Num=" + Data.CheckDeltaTime.Num + " from " + global.NodeInfo(Node)) this.AddCheckErrCount(Node, 10, "Error Sign CheckDeltaTime") } } } } CheckNetConstant(Data, Node) { if (Data.NetConstant.Num > global.NET_CONSTANT.Num) { var SignArr = this.GetSignCheckNetConstant(Data.NetConstant); if (global.CheckDevelopSign(SignArr, Data.NetConstant.Sign)) { global.NET_CONSTANT = Data.NetConstant var CurBlockNum = global.GetCurrentBlockNumByTime(); var Delta = Data.NetConstant.BlockNum - CurBlockNum; if (Delta < 1) Delta = 1 this.ResetNextPingAllNode() global.ToLog("Get new NetConstant (wait " + Delta + " s) Num=" + Data.NetConstant.Num) if (this.idTimerSetConst) clearTimeout(this.idTimerSetConst) let SELF = this; this.idTimerSetConst = setTimeout(function() { SELF.DoNetConst() this.idTimerSetConst = 0 }, Delta * 1000) } else { Node.NextConnectDelta = 60 * 1000 global.ToLog("Error Sign CheckNetConstant Num=" + Data.NetConstant.Num + " from " + global.NodeInfo(Node)) this.AddCheckErrCount(Node, 10, "Error Sign CheckNetConstant") } } } DoNetConst() { global.MAX_TRANSACTION_LIMIT = global.NET_CONSTANT.MaxTrasactionLimit } CheckCodeVersion(Data, Node) { var CodeVersion = Data.CodeVersion; Node.VersionNum = CodeVersion.VersionNum if (CodeVersion.VersionNum >= global.MIN_CODE_VERSION_NUM) { Node.VersionOK = true } else { Node.VersionOK = false } if (Node.VersionOK) { Node.CanHot = true if (global.CHECK_POINT.BlockNum && Data.CheckPoint.BlockNum) if (global.CHECK_POINT.BlockNum !== Data.CheckPoint.BlockNum || global.CompareArr(global.CHECK_POINT.Hash, Data.CheckPoint.Hash) !== 0) { Node.CanHot = false Node.NextConnectDelta = 60 * 1000 } } else { Node.CanHot = false if (!Node.VersionOK) { Node.NextConnectDelta = 60 * 1000 } } var bLoadVer = 0; if (CodeVersion.BlockNum && (CodeVersion.BlockNum <= global.GetCurrentBlockNumByTime() || CodeVersion.BlockPeriod === 0) && CodeVersion.BlockNum > global.CODE_VERSION.BlockNum && !global.IsZeroArr(CodeVersion.Hash) && (CodeVersion.VersionNum > global.CODE_VERSION.VersionNum && CodeVersion.VersionNum > global.START_LOAD_CODE.StartLoadVersionNum || CodeVersion.VersionNum === global.CODE_VERSION.VersionNum && global.IsZeroArr(global.CODE_VERSION.Hash))) { bLoadVer = 1 } if (bLoadVer) { var Level = global.AddrLevelArrFromBegin(this.addrArr, CodeVersion.addrArr); if (CodeVersion.BlockPeriod) { var Delta = global.GetCurrentBlockNumByTime() - CodeVersion.BlockNum; Level += Delta / CodeVersion.BlockPeriod } if (Level >= CodeVersion.LevelUpdate) { var SignArr = global.arr2(CodeVersion.Hash, global.GetArrFromValue(CodeVersion.VersionNum)); if (global.CheckDevelopSign(SignArr, CodeVersion.Sign)) { global.ToLog("Get new CodeVersion = " + CodeVersion.VersionNum + " HASH:" + global.GetHexFromArr(CodeVersion.Hash).substr(0, 20)) if (CodeVersion.VersionNum > global.CODE_VERSION.VersionNum && CodeVersion.VersionNum > global.START_LOAD_CODE.StartLoadVersionNum) { this.StartLoadCode(Node, CodeVersion) } else { global.CODE_VERSION = CodeVersion } } else { global.ToLog("Error Sign CodeVersion=" + CodeVersion.VersionNum + " from " + global.NodeInfo(Node) + " HASH:" + global.GetHexFromArr(CodeVersion.Hash).substr(0, 20)) global.ToLog(JSON.stringify(CodeVersion)) this.AddCheckErrCount(Node, 10, "Error Sign CodeVersion") Node.NextConnectDelta = 60 * 1000 } } } } GetSignCheckNetConstant(Data) { var Buf = global.BufLib.GetBufferFromObject(Data, "{Num:uint,BlockNum:uint,MaxTrasactionLimit:uint,Reserv1:uint,Reserv2:uint,Reserv3:uint,Reserv4:uint,Reserv5:uint}", 1000, {}); return global.shaarr(Buf); } GetSignCheckDeltaTime(Data) { var Buf = global.BufLib.GetBufferFromObject(Data, "{Num:uint,bUse:byte,StartBlockNum:uint,EndBlockNum:uint,bAddTime:byte,DeltaTime:uint}", 1000, {}); return global.shaarr(Buf); } ResetNextPingAllNode() { var arr = global.SERVER.GetActualNodes(); for (var i = 0; i < arr.length; i++) { var Node2 = arr[i]; if (Node2 && Node2.NextPing > 5 * 1000) Node2.NextPing = 5 * 1000 } } StartDisconnectHot(Node, StrError, bDeleteHot?) { global.AddNodeInfo(Node, "DisconnectHot:" + StrError) if (Node.Active && Node.Hot) { global.AddNodeInfo(Node, "SEND DISCONNECTHOT") this.Send(Node, { "Method": "DISCONNECTHOT", "Context": {}, "Data": StrError }, global.STR_TYPE) } this.DeleteNodeFromHot(Node) } DISCONNECTHOT(Info, CurTime) { this.DeleteNodeFromHot(Info.Node) global.ADD_TO_STAT("DISCONNECTHOT") global.AddNodeInfo(Info.Node, "GET DISCONNECTHOT:" + Info.Data) } StartGetNodes(Node) { if (global.glStopNode) return; var Delta = Date.now() - Node.StartTimeGetNodes; if (Delta >= Node.NextGetNodesDelta) { Node.StartTimeGetNodes = Date.now() Node.NextGetNodesDelta = Math.min(Node.NextGetNodesDelta * 2, MAX_PERIOD_GETNODES) if (global.ADDRLIST_MODE) Node.NextGetNodesDelta = MAX_PERIOD_GETNODES this.Send(Node, { "Method": "GETNODES", "Context": {}, "Data": undefined }) } } GETNODES(Info, CurTime) { this.SendF(Info.Node, { "Method": "RETGETNODES", "Context": Info.Context, "Data": { arr: this.GetDirectNodesArray(false, 0, 1), IsAddrList: global.ADDRLIST_MODE, } }, global.MAX_NODES_RETURN * 250 + 300) } static RETGETNODES_F() { return "{arr:[\ {\ addrArr:arr32,\ ip:str20,\ port:uint16,\ portweb:uint16,\ LastTime:uint,\ DeltaTime:uint,\ Reserv:arr8\ }\ ],\ IsAddrList:byte}"; } RETGETNODES(Info, CurTime) { var Data = this.DataFromF(Info); var arr = Data.arr; if (arr && arr.length > 0) { for (var i = 0; i < arr.length; i++) { arr[i].addrStr = global.GetHexFromArr(arr[i].addrArr) var Item = this.AddToArrNodes(arr[i], true); if (Item) Item.LastTimeGetNode = CurTime - 0 } } Info.Node.IsAddrList = Data.IsAddrList global.AddNodeInfo(Info.Node, "RETGETNODES length=" + arr.length) } static RETGETNODES2_F() { return "{arr:[\ {\ addrStr:str64,\ ip:str30,\ port:uint16,\ portweb:uint16,\ LastTime:uint,\ DeltaTime:uint,\ StatData:arr70\ }\ ],\ IsAddrList:byte}"; } RETGETNODES2(Info, CurTime) { var Data = this.DataFromF(Info); var arr = Data.arr; if (arr && arr.length > 0) { for (var i = 0; i < arr.length; i++) { var Item = this.AddToArrNodes(arr[i], true); if (Item) Item.LastTimeGetNode = CurTime - 0 } } Info.Node.IsAddrList = Data.IsAddrList global.AddNodeInfo(Info.Node, "RETGETNODES2 length=" + arr.length) } GetNewNode(ip, port, addrStr?) { var bTemp; if (!addrStr) { bTemp = 1 addrStr = global.GetHexFromAddres(crypto.randomBytes(32)) } var Node = new CNode(addrStr, ip, port); this.AddToArrNodes(Node, false) if (bTemp) Node.addrStrTemp = addrStr return Node; } AddNode(Str) { var ip, port; var Index = Str.indexOf(":"); if (Index > 0) { ip = Str.substr(0, Index) port = ParseNum(Str.substr(Index + 1)) } else { ip = Str if (global.TEST_NETWORK || global.LOCAL_RUN) { port = 40000 } else { port = 30000 } } this.GetNewNode(ip, port) return "AddNode " + ip + ":" + port; } IsCanConnect(Node) { if (Node.addrStr === this.addrStr || this.NodeInBan(Node) || Node.Delete || Node.Self || Node.DoubleConnection) return false; if (Node.ip === this.ip && Node.port === this.port) return false; if (this.addrStr === Node.addrStr) return false; return true; } NodeInBan(Node) { //defiend in } GetDirectNodesArray(bAll, bWebPort?, bGetAddrArr?) { var ret = []; var Value: any = { addrStr: this.addrStr, ip: this.ip, port: this.port, LastTime: 0, DeltaTime: 0, Hot: true, BlockProcessCount: 0, portweb: global.HTTP_HOSTING_PORT, }; if (bGetAddrArr) Value.addrArr = global.GetArrFromHex(Value.addrStr) ret.push(Value) var len = this.NodesArr.length; var UseRandom = 0; var MaxDeltaTime = 24 * 3600 * 1000; if (len > global.MAX_NODES_RETURN && !bAll) { UseRandom = 1 MaxDeltaTime = global.NODES_DELTA_CALC_HOUR * 3600 * 1000 len = global.MAX_NODES_RETURN } var mapWasAdd = {}; var CurTime = global.GetCurrentTime(); for (var i = 0; i < len; i++) { var Item; if (UseRandom) { Item = this.NodesArr[global.random(this.NodesArr.length)] if (mapWasAdd[Item.addrStr]) { continue; } mapWasAdd[Item.addrStr] = 1 } else { Item = this.NodesArr[i] } if (bWebPort && !Item.portweb) continue; if (!this.IsCanConnect(Item)) continue; if (Item.GrayConnect) continue; if (Item.BlockProcessCount < 0) continue; if (!global.GrayConnect() && Item.LastTime - 0 < CurTime - MaxDeltaTime) continue; var Value: any = { addrStr: Item.addrStr, ip: Item.ip, port: Item.port, FirstTime: Item.FirstTime, FirstTimeStr: Item.FirstTimeStr, LastTime: Item.LastTime - 0, DeltaTime: Item.DeltaTime, Hot: Item.Hot, BlockProcessCount: Item.BlockProcessCount, Name: Item.Name, portweb: Item.portweb, }; if (bGetAddrArr) Value.addrArr = global.GetArrFromHex(Value.addrStr) ret.push(Value) } return ret; } AddToArrNodes(Item, b?) { if (Item.addrStr === "" || Item.addrStr === this.addrStr) return; var Node; var key = Item.ip + ":" + Item.port; Node = this.NodesMap[Item.addrStr] if (!Node) { Node = this.NodesIPMap[key] } if (!Node) { if (Item instanceof CNode) Node = Item else Node = new CNode(Item.addrStr, Item.ip, Item.port) Node.id = this.NodesArr.length Node.addrArr = global.GetAddresFromHex(Node.addrStr) this.NodesMap[Node.addrStr] = Node this.NodesArr.push(Node) this.NodesArrUnSort.push(Node) global.ADD_TO_STAT("AddToNodes") } this.NodesMap[Node.addrStr] = Node this.NodesIPMap[key] = Node if (Node.addrArr && global.CompareArr(Node.addrArr, this.addrArr) === 0) { Node.Self = true } if (Item.BlockProcessCount) Node.BlockProcessCount = Item.BlockProcessCount if (Item.FirstTime) { Node.FirstTime = Item.FirstTime Node.FirstTimeStr = Item.FirstTimeStr } if (Item.Name) Node.Name = Item.Name if (Item.portweb) Node.portweb = Item.portweb return Node; } NodesArrSort() { this.NodesArr.sort(SortNodeBlockProcessCount) if ((global.GrayConnect() || !this.LoadHistoryMode) && Date.now() - this.StartTime > 120 * 1000) { var arr0 = this.GetDirectNodesArray(true); var arr = arr0.slice(1, 2000); global.SaveParams(global.GetDataPath("nodes.lst"), arr) } } LoadNodesFromFile() { var arr = global.LoadParams(global.GetDataPath("nodes.lst"), []); arr.sort(SortNodeBlockProcessCount) for (var i = 0; i < arr.length; i++) { if (arr[i].LastTime) { if (typeof arr[i].LastTime === "string") arr[i].LastTime = 0 } this.AddToArrNodes(arr[i], true) } } GetLevelEnum(Node) { var Level = this.AddrLevelNode(Node); var arr0 = this.LevelNodes[Level]; if (!arr0) { Node.LevelEnum = 1 return 1; } var arr = [].concat(arr0); var bWas = 0; for (var n = 0; n < arr.length; n++) { if (arr[n] === Node) { bWas = 1 break; } } if (!bWas) arr.push(Node) arr.sort(SortNodeBlockProcessCount) for (var n = 0; n < arr.length; n++) { if (arr[n] === Node) { Node.LevelEnum = 1 + n break; } } return Node.LevelEnum; } StartAddLevelConnect(Node) { if (!global.CAN_START) return; global.ADD_TO_STAT("NETCONFIGURATION") if (Node.Active && Node.CanHot) this.SendF(Node, { "Method": "ADDLEVELCONNECT", "Context": {}, "Data": this.GetLevelEnum(Node) }) } static ADDLEVELCONNECT_F() { return "uint"; } ADDLEVELCONNECT(Info, CurTime) { Info.Node.LevelCount = this.DataFromF(Info) var ret; var Count; if (!global.CAN_START) return; if (Info.Node.GrayConnect || global.GrayConnect()) return; var Count = this.GetLevelEnum(Info.Node); var bAdd = this.AddLevelConnect(Info.Node); if (bAdd) { ret = { result: 1, Count: Count } } else { ret = { result: 0, Count: Count } } global.AddNodeInfo(Info.Node, "GET ADDLEVELCONNECT, DO bAdd=" + bAdd) this.SendF(Info.Node, { "Method": "RETADDLEVELCONNECT", "Context": Info.Context, "Data": ret }) } AddLevelConnect(Node) { if (!global.CAN_START) return false; var Level = this.AddrLevelNode(Node); Node.Hot = true var arr = this.LevelNodes[Level]; if (!arr) { arr = [] this.LevelNodes[Level] = arr } var bWas = 0; for (var i = 0; i < arr.length; i++) if (arr[i] === Node) { bWas = 1 } if (!bWas) arr.push(Node) Node.TransferCount = 0 if (this.LoadHistoryMode) Node.LastTimeTransfer = (global.GetCurrentTime() - 0) + 30 * 1000 else Node.LastTimeTransfer = (global.GetCurrentTime() - 0) + 10 * 1000 Node.CanHot = true this.CheckDisconnectHot(Level) if (!Node.CanHot) return false; this.SendGetMessage(Node) global.ADD_TO_STAT("NETCONFIGURATION") global.ADD_TO_STAT("AddLevelConnect") global.AddNodeInfo(Node, "Add Level connect") return true; } static RETADDLEVELCONNECT_F() { return "{result:byte,Count:uint}"; } RETADDLEVELCONNECT(Info, CurTime) { var Data = this.DataFromF(Info); global.AddNodeInfo(Info.Node, "GET RETADDLEVELCONNECT: " + Data.result) if (Data.result === 1) { this.AddLevelConnect(Info.Node) } else { this.AddCheckErrCount(Info.Node, 1) } Info.Node.LevelCount = Data.Count } AddCheckErrCount(Node, Count, StrErr?) { //defiend in server.ts } DeleteBadConnectingByTimer() { if (global.glStopNode) return; var CurTime = global.GetCurrentTime(); var arr = global.SERVER.NodesArr; for (var i = 0; i < arr.length; i++) { var Node = arr[i]; var Status = global.GetSocketStatus(Node.Socket); if (Node.Active && Status < 100) { var Delta = CurTime - Node.LastTime; if (Delta > global.MAX_WAIT_PERIOD_FOR_STATUS) { global.AddNodeInfo(Node, "Close bad connecting by time") this.DeleteNodeFromActive(Node) } } } } CheckDisconnectHot(Level) { var CurTime = global.GetCurrentTime() - 0; var MaxCountChilds; if (Level < 3) MaxCountChilds = 4 else MaxCountChilds = global.MAX_CONNECT_CHILD var arr = this.LevelNodes[Level]; if (arr) { for (var n = arr.length - 1; n >= 0; n--) { var Node = arr[n]; if (Node) { var DeltaTime = CurTime - Node.LastTimeTransfer; if (!Node.Hot || DeltaTime > global.MAX_WAIT_PERIOD_FOR_HOT) { this.StartDisconnectHot(Node, "TimeDisconnectHot") } } } arr.sort(SortNodeBlockProcessCount) var ChildCount = arr.length; for (var n = arr.length - 1; n >= global.MIN_CONNECT_CHILD; n--) { var Node = arr[n]; if (Node) { if (ChildCount > MaxCountChilds) { ChildCount-- Node.CanHot = false this.StartDisconnectHot(Node, "MAX_CONNECT_CHILD") global.ADD_TO_STAT("DisconnectChild") continue; } if (ChildCount > (global.MIN_CONNECT_CHILD) && Node.LevelCount > global.MIN_CONNECT_CHILD) { ChildCount-- Node.CanHot = false this.AddCheckErrCount(Node, 1) this.StartDisconnectHot(Node, "MIN_CONNECT_CHILD:" + Node.LevelCount + " LevelEnum:" + (n + 1)) global.ADD_TO_STAT("DisconnectChild") continue; } } } } } SetTime(NewTime) { global.ToLog("Set new time: " + NewTime) if (NewTime) { global.DELTA_CURRENT_TIME = NewTime - (global.GetCurrentTime(0) - 0) global.SAVE_CONST(true) } } static TIME_F() { return "{Time:uint, Sign:arr64}"; } SendTimeDev(Node) { if (!global.WALLET.WalletOpen) { global.ToLog("Error Wallet not open") return 0; } if (!this.SignCurrentTimeDev) { var SignArr = global.GetArrFromHex(global.SERVER.addrStr); this.SignCurrentTimeDev = secp256k1.sign(global.SHA3BUF(SignArr), global.WALLET.KeyPair.getPrivateKey('')).signature } var Time = global.GetCurrentTime() - 0; global.ToLog("Send time: " + Time + " to " + global.NodeInfo(Node)) this.SendF(Node, { "Method": "TIME", "Data": { Time: Time, Sign: this.SignCurrentTimeDev } }) return 1; } SendTimeToAll() { var Count = 0; for (var i = 0; i < this.NodesArr.length; i++) { var Node = this.NodesArr[i]; if (Node.Active) { if (this.SendTimeDev(Node)) Count++ } } return Count; } TIME(Info, CurTime) { if (global.AUTO_CORRECT_TIME) { var Node = Info.Node; var Data = this.DataFromF(Info); var SignArr = global.GetArrFromHex(Node.addrStr); if (global.CheckDevelopSign(SignArr, Data.Sign)) { this.SetTime(Data.Time) } else { Node.NextConnectDelta = 60 * 1000 global.ToLog("Error Sign TIME from " + global.NodeInfo(Node)) this.AddCheckErrCount(Node, 10, "Error Sign TIME") } } } ConnectToAll() { var Count = 0; for (var i = 0; i < this.NodesArr.length; i++) { var Node = this.NodesArr[i]; if (!Node.Active && this.IsCanConnect(Node) && !Node.WasAddToConnect) { global.AddNodeInfo(Node, "To connect all") Node.NextConnectDelta = 1000 Node.WasAddToConnect = 1 global.ArrConnect.push(Node) Count++ } } return Count; } DisconnectAll() { var Count = 0; for (var i = 0; i < this.NodesArr.length; i++) { var Node = this.NodesArr[i]; if (Node.Active) { global.AddNodeInfo(Node, "Disconnect hot all") Node.NextConnectDelta = 10000 this.DeleteNodeFromActive(Node) Count++ } } return Count; } GetHotTimeNodes() { if (this.LoadHistoryMode || !global.CAN_START) return this.GetActualNodes(); else return this.GetHotNodes(); } CorrectTime() { var MaxCorrect = MAX_TIME_CORRECT; var PerioadAfterCanStart = this.PerioadAfterCanStart; var ArrNodes = this.GetHotTimeNodes(); var CountNodes = ArrNodes.length; var DeltaArr = []; var NodesSet: any = new Set(); for (var i = 0; i < ArrNodes.length; i++) { var Node = ArrNodes[i]; if (!Node.Times) continue; if (Node.Times.Count < 2) continue; if (PerioadAfterCanStart >= PERIOD_FOR_START_CHECK_TIME) if (Node.Times.Count < 5) continue; NodesSet.add(Node) } for (var Node of NodesSet) { DeltaArr.push(Node.Times.AvgDelta) } if (DeltaArr.length < 1) return; if (this.LoadHistoryMode && CountNodes > 10) { PerioadAfterCanStart = 0 CountNodes = 10 } if (DeltaArr.length < CountNodes / 2) return; if (PerioadAfterCanStart >= PERIOD_FOR_START_CHECK_TIME) { if (DeltaArr.length < 3 * CountNodes / 4) return; } DeltaArr.sort(function(a, b) { return a - b; }) var start, finish; if (Math.floor(DeltaArr.length / 2) === DeltaArr.length / 2) { start = DeltaArr.length / 2 - 1 finish = start + 1 } else { start = Math.floor(DeltaArr.length / 2) finish = start } var Sum = 0; var Count = 0; //@ts-ignore for (var i = start; i <= finish; i++) { Sum = Sum + DeltaArr[i] Count++ } var AvgDelta = Sum / Count; if (PerioadAfterCanStart < PERIOD_FOR_START_CHECK_TIME) { var KT = (PERIOD_FOR_START_CHECK_TIME - PerioadAfterCanStart) / PERIOD_FOR_START_CHECK_TIME; AvgDelta = AvgDelta * KT } else { MaxCorrect = 25 } if (AvgDelta < (- MaxCorrect)) AvgDelta = - MaxCorrect else if (AvgDelta > MaxCorrect) AvgDelta = MaxCorrect AvgDelta = Math.trunc(AvgDelta) if (Math.abs(AvgDelta) < 15) { return; } if (AvgDelta > 0) global.ADD_TO_STAT("CORRECT_TIME_UP", AvgDelta) else global.ADD_TO_STAT("CORRECT_TIME_DOWN", - AvgDelta) global.DELTA_CURRENT_TIME = Math.trunc(global.DELTA_CURRENT_TIME + AvgDelta) this.ClearTimeStat() global.SAVE_CONST() } ClearTimeStat() { var ArrNodes = this.GetHotTimeNodes(); for (var Node of ArrNodes) { Node.Times = undefined } } TimeDevCorrect() { if (global.CHECK_DELTA_TIME.bUse) { var BlockNum = global.GetCurrentBlockNumByTime(); if (global.CHECK_DELTA_TIME.StartBlockNum <= BlockNum && global.CHECK_DELTA_TIME.EndBlockNum > BlockNum) { if (!global.DELTA_CURRENT_TIME) global.DELTA_CURRENT_TIME = 0 var CorrectTime = 0; if (global.CHECK_DELTA_TIME.bAddTime) CorrectTime = global.CHECK_DELTA_TIME.DeltaTime else CorrectTime = - global.CHECK_DELTA_TIME.DeltaTime global.DELTA_CURRENT_TIME += CorrectTime this.ClearTimeStat() global.SAVE_CONST(true) } } } SetNodePrioritet(Node, Prioritet) { if (Node.Prioritet === Prioritet) return; if (Node.addrArr) { var Item = this.ActualNodes.find(Node); if (Item) { this.ActualNodes.remove(Node) Node.Prioritet = Prioritet this.ActualNodes.insert(Node) } } Node.Prioritet = Prioritet } AddNodeToActive(Node) { if (Node.addrArr) { if (global.CompareArr(Node.addrArr, this.addrArr) === 0) { return; } this.CheckNodeMap(Node) this.ActualNodes.insert(Node) } Node.ResetNode() Node.Active = true Node.NextConnectDelta = 1000 if (!Node.FirstTime) { Node.FirstTime = global.GetCurrentTime() - 0 Node.FirstTimeStr = "" + global.GetStrTimeUTC() } global.ADD_TO_STAT("AddToActive") } DeleteNodeFromActive(Node) { Node.Active = false if (Node.Hot) this.StartDisconnectHot(Node, "NotActive", 1) Node.Hot = false this.ActualNodes.remove(Node) global.CloseSocket(Node.Socket, "DeleteNodeFromActive") global.CloseSocket(Node.Socket2, "DeleteNodeFromActive") Node.ResetNode() Node.Socket = undefined Node.Socket2 = undefined } StartReconnect() { return; var arr = this.GetActualNodes(); for (var i = 0; i < arr.length; i++) { var Node = arr[i]; if (Node.Socket && Node.Socket.ConnectToServer) { if (!Node.SocketStart) Node.SocketStart = Date.now() var DeltaTime = Date.now() - Node.SocketStart; if (DeltaTime >= global.PERIOD_FOR_RECONNECT) { if (global.random(100) >= 90) Node.CreateReconnection() } } } } IsLocalIP(addr) { if (addr.substr(0, 7) === "192.168" || addr.substr(0, 3) === "10.") return 1; else return 0; } GetActualsServerIP(bFlag) { var arr = this.GetActualNodes(); var Str = ""; arr.sort(function(a, b) { if (a.ip > b.ip) return - 1; else if (a.ip < b.ip) return 1; else return 0; }) if (bFlag) return arr; for (var i = 0; i < arr.length; i++) { Str += arr[i].ip + ", " } return Str.substr(0, Str.length - 2); } AddrLevelNode(Node) { if (Node.GrayConnect) return global.MAX_LEVEL_SPECIALIZATION - 1; return global.AddrLevelArr(this.addrArr, Node.addrArr); } GetNodesLevelCount() { var Count = 0; for (var i = 0; i < this.LevelNodes.length; i++) { var arr = this.LevelNodes[i]; for (var n = 0; arr && n < arr.length; n++) if (arr[n].Hot) { Count++ break; } } return Count; } GetHotNodes() { var ArrNodes = []; for (var L = 0; L < this.LevelNodes.length; L++) { var arr = this.LevelNodes[L]; for (let j = 0; arr && j < arr.length; j++) { ArrNodes.push(arr[j]) } } return ArrNodes; } DeleteNodeFromHot(Node) { if (Node.Hot) { Node.Hot = false } Node.CanHot = false for (var i = 0; i < this.LevelNodes.length; i++) { var arr = this.LevelNodes[i]; for (var n = 0; arr && n < arr.length; n++) if (arr[n] === Node) { arr.splice(n, 1) global.ADD_TO_STAT("DeleteLevelConnect") global.ADD_TO_STAT("NETCONFIGURATION") break; } } } DeleteAllNodesFromHot(Str) { for (var i = 0; i < this.LevelNodes.length; i++) { var arr = this.LevelNodes[i]; for (var n = 0; arr && n < arr.length; n++) { var Node = arr[n]; if (Node.Hot) { global.ADD_TO_STAT("DeleteAllNodesFromHot") this.StartDisconnectHot(Node, Str, 1) } } } } GetTransferTree() { var HotArr = []; for (var Level = 0; Level < this.LevelNodes.length; Level++) { var arr = this.LevelNodes[Level]; HotArr[Level] = [] for (var n = 0; arr && n < arr.length; n++) { var Node = arr[n]; if (Node) { Node.Hot = 1 Node.Level = Level HotArr[Level].push(Node) } } } var arr = this.NodesArr; for (var n = 0; arr && n < arr.length; n++) { var Node = arr[n]; if (!Node) continue; if (Node.Hot) continue; if (!this.IsCanConnect(Node)) continue; Node.Level = this.AddrLevelNode(Node) if (!HotArr[Node.Level]) HotArr[Node.Level] = [] HotArr[Node.Level].push(Node) } return HotArr; } DetectGrayMode() { if (global.NET_WORK_MODE) return; var CurTime = Date.now(); var CountNodes = this.ActualNodes.size; if (CountNodes || this.StopDetectGrayMode) { this.SetDirectMode() this.StopDetectGrayMode = 1 return; } if (!this.LastNotZeroNodesTime) this.LastNotZeroNodesTime = CurTime var DeltaTime = CurTime - this.LastNotZeroNodesTime; if (DeltaTime > 10 * 1000) { global.ToLog("DETECT GRAY MODE") if (!global.NET_WORK_MODE) { global.NET_WORK_MODE = { ip: "", port: "" } } global.NET_WORK_MODE.UseDirectIP = 0 global.SAVE_CONST() } } SetDirectMode() { var CountNodes = this.ActualNodes.size; if (CountNodes && !global.NET_WORK_MODE) { global.NET_WORK_MODE = { ip: "", port: "30000" } global.NET_WORK_MODE.UseDirectIP = 1 global.SAVE_CONST() } } StartCheckTransferTree() { var ArrTree = this.GetTransferTree(); this.TransferTree = ArrTree var CurTime = Date.now(); if (global.GrayConnect()) { var MustCount = GetGrayServerConnections(); if (this.ActualNodes.size < MustCount) { this.NodesArr.sort(SortNodeBlockProcessCountGray) var WasDoConnect = 0; var arr = this.NodesArr; for (var n = 0; arr && n < arr.length; n++) { var Node = arr[n]; if (!Node) continue; if (!this.IsCanConnect(Node)) continue; var DeltaTime = CurTime - Node.StartTimeConnect; if (!Node.Active && WasDoConnect < 5 && !Node.WasAddToConnect && DeltaTime >= Node.NextConnectDelta) { global.AddNodeInfo(Node, "To connect") Node.WasAddToConnect = 1 global.ArrConnect.push(Node) WasDoConnect++ } } } while (this.ActualNodes.size > MustCount) { var Node = this.ActualNodes.max(); global.AddNodeInfo(Node, "DeleteFromActive") this.DeleteNodeFromActive(Node) } } else { this.DetectGrayMode() for (var Level = 0; Level < ArrTree.length; Level++) { var arr = ArrTree[Level]; if (!arr) continue; arr.sort(SortNodeBlockProcessCount) var WasDoConnect = 0; var WasDoHot = 0; var length = Math.min(arr.length, 10); for (var n = 0; n < length; n++) { var Node = arr[n]; var DeltaTime = CurTime - Node.StartTimeConnect; if (!Node.Active && WasDoConnect < 5 && !Node.WasAddToConnect && DeltaTime >= Node.NextConnectDelta) { global.AddNodeInfo(Node, "To connect") Node.WasAddToConnect = 1 global.ArrConnect.push(Node) WasDoConnect++ } DeltaTime = CurTime - Node.StartTimeHot if (Node.Active && !Node.Hot && WasDoHot < global.MIN_CONNECT_CHILD && DeltaTime > Node.NextHotDelta && !Node.GrayConnect) { global.AddNodeInfo(Node, "To hot level") this.StartAddLevelConnect(Node) Node.StartTimeHot = CurTime Node.NextHotDelta = Node.NextHotDelta * 2 WasDoHot++ } if (Node.Hot) WasDoHot++ } this.CheckDisconnectHot(Level) } } } ValueToXOR(StrType, Str) { var Arr1 = global.toUTF8Array(Str); var Arr2 = global.shaarr(this.CommonKey + ":" + this.addrStr + ":" + StrType); return global.WALLET.XORHash(Arr1, Arr2, 32); } ValueFromXOR(Node, StrType, Arr1) { var Arr2 = global.shaarr(this.CommonKey + ":" + Node.addrStr + ":" + StrType); var Arr = global.WALLET.XORHash(Arr1, Arr2, 32); var Str = global.Utf8ArrayToStr(Arr); return Str; } ValueToXORDevelop(StrName, Data, Type) { var Arr1; if (Type === "uint") { Arr1 = [] global.WriteUintToArr(Arr1, Data) } else if (Type === "hash") { Arr1 = Data } else if (Type === "str") { Arr1 = global.toUTF8Array(Data) } var Arr2 = global.shaarr(this.КодДляРазработчикаХекс + ":" + StrName); return global.WALLET.XORHash(Arr1, Arr2, Arr1.length); } ValueFromXORDevelop(Node, StrName, Arr1, Type) { if (!Node.КодДляРазработчикаХекс) { Node.КодДляРазработчикаХекс = global.GetHexFromArr(global.WALLET.KeyPair.computeSecret(Node.PubKey, null)) } var Arr2 = global.shaarr(Node.КодДляРазработчикаХекс + ":" + StrName); var Arr = global.WALLET.XORHash(Arr1, Arr2, Arr1.length); if (Type === "uint") { return global.ReadUintFromArr(Arr, 0); } else if (Type === "hash") { return Arr; } var Str = global.Utf8ArrayToStr(Arr); return Str; } }; function SortNodeBlockProcessCount(a, b) { if (b.BlockProcessCount !== a.BlockProcessCount) return b.BlockProcessCount - a.BlockProcessCount; if (a.DeltaTime !== b.DeltaTime) return a.DeltaTime - b.DeltaTime; return a.id - b.id; }; function SortNodeBlockProcessCountGray(a, b) { if (a.StartFindList !== b.StartFindList) return a.StartFindList - b.StartFindList; if (b.BlockProcessCount !== a.BlockProcessCount) return b.BlockProcessCount - a.BlockProcessCount; if (a.DeltaTime !== b.DeltaTime) return a.DeltaTime - b.DeltaTime; return a.id - b.id; }; function GetGrayServerConnections() { var Count = global.MAX_GRAY_CONNECTIONS_TO_SERVER; if (global.SERVER.LoadHistoryMode && global.SERVER.LoadHistoryMessage) Count = Count * 10; return Count; }; global.GetGrayServerConnections = GetGrayServerConnections; global.SortNodeBlockProcessCount = SortNodeBlockProcessCount;