tera/src/core/connect.ts

1399 lines
54 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* @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'
import { TeraBlock, SocketSendInfo } from '../interfaces/server';
export default class CConnect extends CMessages {
ip: string
port: number | string
StartTime: number
WasNodesSort: boolean
LevelNodes: any[]
NodesArr: CNode[]
NodesArrUnSort: CNode[]
NodesMap: { [x: string]: CNode; }
NodesIPMap: { [x: string]: any; }
PerioadAfterCanStart: number
КодДляРазработчикаХекс: string
CommonKey: string
KeyToNode: Buffer
NameToNode: any
BlockNumDB: number
idTimerSetConst: NodeJS.Timeout
SignCurrentTimeDev: Buffer
StopDetectGrayMode: number
LastNotZeroNodesTime: number
TransferTree: any[]
СтатБлок: { SeqHash: any; BlockNum: any; AddrHash: any; }
BusyLevel: number
SendTrafficFree: number
constructor(SetKeyPair: crypto.ECDH, RunIP: string, RunPort: number, UseRNDHeader: boolean, bVirtual: boolean) {
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: CNode) {
if (Node.PubKey && global.WALLET.WalletOpen !== false && global.IsDeveloperAccount(global.WALLET.PubKeyArr)) {
return 1;
}
return 0;
}
БлокИзДанных(Node: CNode, Arr: any) {
var Block: TeraBlock = {};
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: CNode) {
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: Buffer, ip: string, port: number, bUpdate: boolean) {
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: CNode) {
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: CNode) {
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: CNode) {
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: boolean) {
return CConnect.PING_F(bSend);
}
PING(Info: SocketSendInfo, CurTime: number) {
this.DoPingData(Info, 1)
this.SendF(Info.Node, { "Method": "PONG", "Context": Info.Context, "Data": this.GetPingData(Info.Node) })
}
DoPingData(Info: SocketSendInfo, bCheckPoint: number) {
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 = true
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: SocketSendInfo, CurTime: number) {
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: { CheckPoint: { BlockNum: string | number; Hash: any; Sign: any; }; }, Node: CNode) {
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, false, true)
}
} 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: { CheckDeltaTime: { Num: string | number; Sign: any; }; }, Node: CNode) {
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: { NetConstant: { Num: string | number; Sign: any; BlockNum: number; }; }, Node: CNode) {
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: { CodeVersion: any; CheckPoint: { BlockNum: any; Hash: any[] | Buffer; }; }, Node: CNode) {
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: { Num: string | number; Sign: any; BlockNum: number; }) {
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: { Num: string | number; Sign: any; }) {
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: CNode, StrError: string, bDeleteHot?: boolean) {
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: { Node: any; Data: string; }, CurTime: any) {
this.DeleteNodeFromHot(Info.Node)
global.ADD_TO_STAT("DISCONNECTHOT")
global.AddNodeInfo(Info.Node, "GET DISCONNECTHOT:" + Info.Data)
}
StartGetNodes(Node: CNode) {
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: { Node: CNode; Context: any; }, CurTime: number) {
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: SocketSendInfo, CurTime: number) {
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)
}
GetNewNode(ip: string, port: number, addrStr?: string) {
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: string) {
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: CNode) {
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: CNode) {
//defiend in
}
GetDirectNodesArray(bAll: boolean, bWebPort?: number, bGetAddrArr?: number) {
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: CNode, b?: boolean) {
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 {
let item = Item as { addrStr: string, ip: string, port: number }
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: CNode) {
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;
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: CNode) {
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: SocketSendInfo, CurTime: number) {
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: CNode, Count: number, StrErr?: string) {
//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: number) {
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: number) {
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: CNode) {
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: SocketSendInfo, CurTime: number) {
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: CNode, Prioritet: number) {
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: CNode) {
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: CNode) {
Node.Active = false
if (Node.Hot)
this.StartDisconnectHot(Node, "NotActive", true)
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: string) {
if (addr.substr(0, 7) === "192.168" || addr.substr(0, 3) === "10.")
return 1;
else
return 0;
}
GetActualsServerIP(bFlag: boolean) {
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: CNode) {
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: CNode) {
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: string) {
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, true)
}
}
}
}
GetTransferTree() {
var HotArr = [];
for (var Level = 0; Level < this.LevelNodes.length; Level++) {
let 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)
}
}
}
let arr = this.NodesArr;
for (var n = 0; arr && n < arr.length; n++) {
let 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 > 60 * 1000) {
global.ToLog("DETECT GRAY MODE")
if (!global.NET_WORK_MODE) {
global.NET_WORK_MODE = { ip: "", port: 30000 }
}
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", NOT_RUN: 0 }
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++) {
let 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++) {
let 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: string, Str: string) {
var Arr1 = global.toUTF8Array(Str);
var Arr2 = global.shaarr(this.CommonKey + ":" + this.addrStr + ":" + StrType);
return global.WALLET.XORHash(Arr1, Arr2, 32);
}
ValueFromXOR(Node: CNode, StrType: string, Arr1: any) {
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: string, Data: any, Type: string) {
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: CNode, StrName: string, Arr1: { length: any; }, Type: string) {
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: CNode, b: CNode) {
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: CNode, b: CNode) {
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;