1399 lines
54 KiB
TypeScript
1399 lines
54 KiB
TypeScript
/*
|
||
* @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;
|