forked from circlecloud/tera
1
0
Fork 0
tera/src/core/block-exchange.ts

1438 lines
57 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 CBlock from './block-loader'
import { RBTree } from './library'
import { STreeBuffer } from './base';
import { teraManager } from '../rpc/manager'
require('./library');
require('./crypto-library');
const TX_PROCESS_TIME = 100;
const TX_DELTA_PROCESS_TIME = 300;
global.CAN_START = false;
global.StrWarn = "";
global.SUM_LIST_LENGTH = 2 * global.BLOCK_PROCESSING_LENGTH;
global.CONSENSUS_TIK_TIME = global.CONSENSUS_PERIOD_TIME / 10;
global.CONSENSUS_CHECK_TIME = global.CONSENSUS_PERIOD_TIME / 20;
const PERIOD_FOR_NEXT_SEND = global.CONSENSUS_TIK_TIME * 3;
global.BLOCK_DELTA_ACTIVATE = 0;
global.TIME_END_EXCHANGE = - 3;
global.TIME_START_POW = - 4;
global.TIME_START_SAVE = - 4;
global.TIME_START_LOAD = global.TIME_START_SAVE - 4;
var FORMAT_DATA_TRANSFER = "{\
Version:uint16,\
BlockNum:uint,\
Reserv1:uint32,\
MaxPOW:[{BlockNum:uint,AddrHash:hash,SeqHash:hash}],\
Reserv2:uint32,\
BaseBlockNum:uint,\
MaxSumID:[{BlockNum:uint,SumHash:hash,SumListID:[uint16]}],\
BlockList:[{ID:uint16, AddrHash:hash,SeqHash:hash}],\
TicketArray:[{HashTicket:arr10}],\
TxArray:[{body:tr}],\
NoSendTx:uint,\
}";
const WorkStructSend = {};
export default class CConsensus extends CBlock {
CurrentBlockNum
SendBlockID
RelayMode
TreeSendPacket
idBlockChainTimer
OwnBlockCount
LevelNodes
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
this.CurrentBlockNum = 0
this.SendBlockID = 0
this.RelayMode = false
this.TreeSendPacket = new RBTree(global.CompareItemHash)
if (!global.ADDRLIST_MODE && !this.VirtualMode) {
this.idBlockChainTimer = setInterval(this.StartBlockChain.bind(this), global.CONSENSUS_PERIOD_TIME - 5)
setInterval(this.DoTransfer.bind(this), global.CONSENSUS_CHECK_TIME)
}
}
StartBlockChain() {
this.OnStartSecond()
var CurTimeNum = global.GetCurrentTime() - global.CONSENSUS_PERIOD_TIME / 2;
var StartTimeNum = Math.floor((CurTimeNum + global.CONSENSUS_PERIOD_TIME) / global.CONSENSUS_PERIOD_TIME) * global.CONSENSUS_PERIOD_TIME;
var DeltaForStart = StartTimeNum - CurTimeNum;
if (DeltaForStart < (global.CONSENSUS_PERIOD_TIME - 5)) {
var self = this;
if (self.idBlockChainTimer)
clearInterval(self.idBlockChainTimer)
self.idBlockChainTimer = 0
setTimeout(function() {
self.idBlockChainTimer = setInterval(self.StartBlockChain.bind(self), global.CONSENSUS_PERIOD_TIME)
self.OnStartSecond()
}, DeltaForStart)
}
}
OnStartSecond() {
global.PrepareStatEverySecond()
this.AddStatOnTimer()
this.DoBlockChain()
}
CreateBlockContext() {
var Context: any = {};
Context.AddInfo = global.AddInfoBlock.bind(Context)
Context.Active = false
Context.TransferFromAddr = {}
Context.LevelsTransfer = []
Context.ErrRun = ""
Context.PowTxTree = new RBTree(global.CompareItemTimePow)
Context.PowTicketTree = new RBTree(global.CompareItemTimePow)
Context.bSave = false
Context.PrevHash = undefined
Context.TreeHash = undefined
Context.MaxPOW = {}
Context.MaxSum = {}
Context.SumPow = 0
Context.Power = 0
Context.TrCount = 0
Context.TrDataPos = 0
Context.TrDataLen = 0
Context.Info = "Create at:" + global.GetStrOnlyTimeUTC()
var Transfer;
var TransferM2;
var LocalLevel = 0;
var Levels = this.LevelNodes;
for (let L = 0; L < Levels.length; L++) {
var arr = Levels[L];
if (arr && arr.length > 0) {
Transfer = {
LocalLevel: LocalLevel, TreeLevel: L, SendCount: 0, GetCount: 0, TransferNodes: {}, WasGet: false, WasSend: false, MustDeltaTime: global.CONSENSUS_TIK_TIME * (2 + global.MAX_LEVEL_SPECIALIZATION - L),
}
LocalLevel++
Context.LevelsTransfer.push(Transfer)
Context.StartLevel = Context.LevelsTransfer.length - 1
for (let j = 0; j < arr.length; j++) {
var Node = arr[j];
var Addr = Node.addrStr;
if (!Transfer.TransferNodes[Addr]) {
let Item = { Node: Node, SendCount: 0, GetCount: 0, addrStr: Addr, TreeLevel: L, GetTiming: 3 * global.CONSENSUS_PERIOD_TIME, };
Transfer.TransferNodes[Addr] = Item
}
Context.TransferFromAddr[Addr] = Transfer
}
}
}
Context.MLevelSend = Context.StartLevel
return Context;
}
StartConsensus() {
if (!global.CAN_START)
return;
var StartBlockNum = global.GetCurrentBlockNumByTime();
if (StartBlockNum < global.BLOCK_PROCESSING_LENGTH2)
return;
this.CurrentBlockNum = StartBlockNum
var Block0 = this.GetBlockContext(StartBlockNum - global.BLOCK_DELTA_ACTIVATE);
if (!Block0.Active) {
global.AddInfoBlock(Block0, "Activate")
this.StartBlock(Block0)
} else {
global.AddInfoBlock(Block0, "Was Active")
}
}
TrToInfo(Block, Array, StrInfo) {
var Str = "";
for (var i = 0; i < Array.length; i++) {
var Item = Array[i];
this.CheckCreateTransactionObject(Item)
Str += this.GetStrFromHashShort(global.shaarr(Item.body)) + "(" + Item.body.length + "),"
}
global.AddInfoBlock(Block, "" + StrInfo + ": Arr=[" + Str + "]")
}
TRANSFER(Info, CurTime) {
var startTime = process.hrtime();
var Data = this.DataFromF(Info);
var Node = Info.Node;
Node.TransferBlockNum = Data.BlockNum
Node.CurBlockNum = Data.BaseBlockNum + Data.BlockNum
if (Data.Version !== 5)
return;
var Block = this.GetBlockContext(Data.BlockNum);
if (!Block || Block.StartLevel === undefined) {
global.ADD_TO_STAT("TRANSFER_ERR_STARTLEVEL")
this.AddCheckErrCount(Node, 1, "Err GetBlockContext")
return;
}
if (!Block.Active)
this.StartBlock(Block)
var Key = Node.addrStr;
var Transfer = Block.TransferFromAddr[Key];
if (!Transfer) {
global.ADD_TO_STAT("NO_TRANSFER")
this.AddCheckErrCount(Node, 1, "Err Transfer")
return;
}
Transfer.WasGet = true
if (global.DoTxLog && Data.TicketArray.length)
global.ToLog("TRANSFER BlockNum:" + Block.BlockNum + " TicketArray=" + Data.TicketArray.length + " from " + global.NodeName(Node))
if (global.DoTxLog && Data.TxArray.length)
global.ToLog("TRANSFER BlockNum:" + Block.BlockNum + " TxArray=" + Data.TxArray.length + " from " + global.NodeName(Node))
this.ToMaxPOWList(Data.MaxPOW)
this.ToMaxSumList(this.GetMaxSumListFromID(Node, Data.MaxSumID, Data.BlockList))
var WasNewAdd = 0;
if (Data.TxArray.length) {
for (var i = 0; i < Data.TxArray.length; i++) {
var Tr = Data.TxArray[i];
var Res = this.AddTrToBlockQuote(Block, Tr);
if (Res === 1) {
WasNewAdd = 1
}
if (global.USE_CHECK_SENDING && Res > 0) {
var Tt = Block.PowTxTree.find(Tr);
if (Tt) {
if (!Tt.NodesList)
Tt.NodesList = []
Tt.NodesList.push(Node)
Tt.TreeLevel = Transfer.TreeLevel
}
}
}
}
else {
for (var i = 0; i < Data.TicketArray.length; i++) {
var Tr = this.AddTicketToBlockQuote(Block, Data.TicketArray[i]);
if (Tr) {
if (!Tr.NodesList)
Tr.NodesList = []
Tr.NodesList.push(Node)
}
}
}
global.ADD_TO_STAT_TIME("TRANSFER_MS", startTime)
var Delta = Date.now() - this.StartLoadBlockTime;
if (Delta > 10 * 1000 && Node.TransferCount > 10) {
Node.BlockProcessCount++
Node.NextHotDelta = 10 * 1000
}
Node.TransferCount++
Node.LastTimeTransfer = global.GetCurrentTime() - 0
var Item = Transfer.TransferNodes[Key];
Item.GetTiming = global.GetCurrentTime(Block.DELTA_CURRENT_TIME) - Block.StartTimeNum
if (!Block.TransferNodesCount)
Block.TransferNodesCount = 0
Block.TransferNodesCount++
}
DoTransfer() {
if (global.glStopNode)
return;
if (!global.CAN_START)
return;
var MaxPOWList;
var MaxSumList;
var start = this.CurrentBlockNum - global.BLOCK_PROCESSING_LENGTH;
var finish = this.GetLastCorrectBlockNum();
for (var b = start; b <= finish; b++) {
var Block = this.GetBlock(b);
if (!Block)
continue;
if (Block.StartLevel === undefined || Block.MLevelSend === undefined)
continue;
if (!Block.Active)
continue;
if (global.USE_TICKET)
this.DoJobListTX(Block)
if (Block.MLevelSend < 0) {
this.CheckEndExchange(Block)
continue;
}
if (Block.EndExchange)
continue;
var Transfer = Block.LevelsTransfer[Block.MLevelSend];
if (!Transfer.WasSend) {
if (!MaxPOWList) {
MaxPOWList = this.GetMaxPOWList()
MaxSumList = this.GetMaxSumList()
}
var ArrT;
if (global.USE_TICKET)
ArrT = this.GetArrayFromTicketTree(Block)
else
ArrT = this.GetArrayFromTxTree(Block)
this.SendDataTransfer(Transfer, ArrT, MaxPOWList, MaxSumList, Block)
}
Transfer.WasSend = true
var bNext = Transfer.WasGet;
if (!bNext) {
var CurTimeNum = global.GetCurrentTime(Block.DELTA_CURRENT_TIME) - 0;
var DeltaTime = CurTimeNum - Block.StartTimeNum;
if (DeltaTime > Transfer.MustDeltaTime) {
bNext = true
Block.ErrRun = "" + Transfer.LocalLevel + " " + Block.ErrRun
for (var Addr in Transfer.TransferNodes) {
var Item = Transfer.TransferNodes[Addr];
global.ADD_TO_STAT("TRANSFER_TIME_OUT")
this.AddCheckErrCount(Item.Node, 1, "TRANSFER_TIME_OUT")
}
global.ADD_TO_STAT("TimeOutLevel")
}
}
if (bNext) {
if (Block.MLevelSend === 0) {
Block.EndExchangeTime = Date.now()
if (!global.USE_TICKET)
this.CheckEndExchange(Block)
}
Block.MLevelSend--
}
}
}
CheckEndExchange(Block) {
if (Block.EndExchange)
return;
if (!global.USE_TICKET) {
this.CreateTreeHash(Block)
return;
}
if (!Block.JobListTX || !Block.EndExchangeTime)
return;
var CurTime = Date.now();
var Delta = CurTime - Block.EndExchangeTime;
if (Delta >= TX_DELTA_PROCESS_TIME * 2) {
if (global.DoTxLog)
global.ToLog("END:" + Block.BlockNum + " -> CreateTreeHash")
this.CreateTreeHash(Block)
}
}
SendDataTransfer(Transfer, ArrT, MaxPOWList, MaxSumList, Block) {
for (var Addr in Transfer.TransferNodes) {
var Item = Transfer.TransferNodes[Addr];
Transfer.SendCount++
var arrPow = [];
for (var i = 0; i < MaxPOWList.length; i++) {
var elem = MaxPOWList[i];
var Str = "POW:" + Item.Node.id + elem.BlockNum + "-" + global.GetHexFromArr(elem.AddrHash);
var bWasSend = global.TreeBlockBuf.LoadValue(Str, 1);
if (!bWasSend) {
global.TreeBlockBuf.SaveValue(Str, true)
arrPow.push(elem)
}
}
var arrSum = [];
for (var i = 0; i < MaxSumList.length; i++) {
var elem = MaxSumList[i];
var Str = "MAX:" + Item.Node.id + elem.BlockNum + "-" + global.GetHexFromArr(elem.SumHash);
var bWasSend = global.TreeBlockBuf.LoadValue(Str, 1);
if (!bWasSend) {
global.TreeBlockBuf.SaveValue(Str, true)
arrSum.push(elem)
}
}
var Arr;
if (global.USE_CHECK_SENDING)
Arr = this.FilterArrForSendNode(Block, Item.Node, ArrT, global.USE_TICKET)
else
Arr = ArrT
if (global.USE_LEVEL_WAY) {
var Arr2 = [];
for (var t = 0; t < Arr.length; t++) {
var Tr = Arr[t];
if (Tr.TreeLevel !== Transfer.TreeLevel)
Arr2.push(Tr)
}
Arr = Arr2
}
if (global.DoTxLog)
global.ToLog("SEND TRANSFER BlockNum:" + Block.BlockNum + " Arr=" + Arr.length + " to " + global.NodeName(Item.Node))
var BufData = this.CreateTransferBuffer(Arr, arrPow, arrSum, Block, Item.Node);
this.Send(Item.Node, { "Method": "TRANSFER", "Context": {}, "Data": BufData }, 1)
if (!Block.JobListTX)
Block.JobListTX = []
Block.JobListTX.push({ Node: Item.Node, TreeLevel: Item.TreeLevel, Time: Date.now() })
}
}
Send(Node, Info, TypeData?) {
// defiend in server.ts
}
TRANSFERTX(Info, CurTime) {
var Data = this.DataFromF(Info);
var Node = Info.Node;
var Block = this.GetBlockContext(Data.BlockNum);
if (!Block) {
return;
}
if (global.DoTxLog)
global.ToLog("TRANSFERTX BlockNum:" + Block.BlockNum + " Array=" + Data.Array.length + " from " + global.NodeName(Node))
for (var i = 0; i < Data.Array.length; i++) {
this.AddTrToBlockQuote(Block, Data.Array[i], 1)
}
}
static TRANSFERTX_F() {
return "{BlockNum:uint, Array:[{body:tr}]}";
}
static GETTRANSFERTX_F() {
return "{BlockNum:uint, TicketArray:[{HashTicket:arr10}]}";
}
GETTRANSFERTX(Info, CurTime) {
return;
var Data = this.DataFromF(Info);
var Node = Info.Node;
var Block = this.GetBlockContext(Data.BlockNum);
if (!Block) {
return;
}
this.SendTrByTickets(Info, Node, Block, Data.TicketArray, 10)
}
CanSendTest() {
return 1;
}
SendTrByTickets(Info, Node, Block, ArrTT, CountTrySend) {
if (!Block.PowTxTree)
return;
var Arr = [];
var bFindTT = 0;
var BufLength = 0;
for (var i = 0; i < ArrTT.length; i++) {
var Tr = ArrTT[i];
this.CheckCreateTicketObject(Tr, Block.BlockNum)
var Tr0 = Block.PowTxTree.find(Tr);
if (Tr0) {
if (Tr0.IsTx) {
if (this.CanSendTest())
Arr.push(Tr0)
BufLength += Tr0.body.length
if (BufLength > global.MAX_BLOCK_SIZE)
break;
}
else {
bFindTT = 1
}
}
}
if (bFindTT && CountTrySend) {
let SELF = this;
setTimeout(function() {
SELF.SendTrByTickets(Info, Node, Block, ArrTT, CountTrySend - 1)
}, 100)
return;
}
if (!Arr.length)
return;
var SendData = { "Method": "RETTRANSFERTX", "Context": Info.Context, "Data": { BlockNum: Block.BlockNum, Array: Arr, } };
this.SendF(Node, SendData, global.MAX_BLOCK_SIZE + 1000)
}
static RETTRANSFERTX_F() {
return "{BlockNum:uint,Array:[{body:tr}]}";
}
RETTRANSFERTX(Info, CurTime) {
return;
var Data = this.DataFromF(Info);
var Node = Info.Node;
Node.TransferBlockNum = Data.BlockNum
var Block = this.GetBlockContext(Data.BlockNum);
if (!Block || !Block.PowTxTree) {
return;
}
if (global.DoTxLog)
global.ToLog("RETTRANSFERTX BlockNum:" + Block.BlockNum + " Array=" + Data.Array.length + " from " + global.NodeName(Node))
for (var i = 0; i < Data.Array.length; i++) {
var Tr = Data.Array[i];
this.CheckCreateTransactionObject(Tr)
var Tr0 = Block.PowTxTree.find(Tr);
if (Tr0) {
if (!Tr0.IsTx) {
Tr0.IsTx = 1
Tr0.body = Tr.body
Tr0.HASH = Tr.HASH
}
}
}
}
DoJobListTX(Block) {
if (Block.EndExchange || !Block.JobListTX || !Block.PowTicketTree)
return;
var ArrTx;
var CurTime = Date.now();
for (var i = 0; i < Block.JobListTX.length; i++) {
var JobItem = Block.JobListTX[i];
var Delta = CurTime - JobItem.Time;
if (!JobItem.WasSend && Delta >= TX_DELTA_PROCESS_TIME) {
JobItem.WasSend = 1
if (!ArrTx)
ArrTx = this.GetArrayFromTxTree(Block)
var Arr = this.FilterArrForSendNode(Block, JobItem.Node, ArrTx);
if (!Arr.length)
return;
if (global.DoTxLog)
global.ToLog("DoJobListTX BlockNum:" + Block.BlockNum + " Arr=" + Arr.length + " to " + global.NodeName(JobItem.Node))
var SendData = { "Method": "TRANSFERTX", "Context": {}, "Data": { BlockNum: Block.BlockNum, Array: Arr, } };
this.SendF(JobItem.Node, SendData, global.MAX_BLOCK_SIZE + 1000)
}
}
}
FindNodeTicket(Block, Tr, Node, bTt) {
var Ticket;
if (bTt)
Ticket = Tr
else
Ticket = Block.PowTicketTree.find(Tr)
if (Ticket && Ticket.NodesList) {
for (var n = 0; n < Ticket.NodesList.length; n++) {
var NodeItem = Ticket.NodesList[n];
if (NodeItem === Node) {
return 1;
}
}
}
return 0;
}
FilterArrForSendNode(Block, Node, ArrTx, bTt?) {
var Arr = [];
for (var t = 0; t < ArrTx.length; t++) {
var Tr = ArrTx[t];
if (this.FindNodeTicket(Block, Tr, Node, bTt))
continue;
Arr.push(Tr)
}
return Arr;
}
CheckEndExchange00(Block) {
if (Block.EndExchange)
return;
var CurTime = Date.now();
var CanEnd = 1;
var bSend = 0;
var it = Block.PowTxTree.iterator(), Tr;
while ((Tr = it.next()) !== null) {
if (!Tr.IsTx) {
if (!Tr.LastProcessTime)
throw "!Tr.LastProcessTime";
var Delta = CurTime - Tr.LastProcessTime;
if (Delta < TX_PROCESS_TIME * 10) {
bSend = 1
CanEnd = 0
break;
} else {
var Stop = 1;
}
}
}
if (CanEnd) {
if (global.DoTxLog)
global.ToLog("END:" + Block.BlockNum + " -> CreateTreeHash")
this.CreateTreeHash(Block)
}
else
if (bSend) {
this.CheckTxExchange(Block, bSend)
}
}
CheckTxExchange(Block, b?) {
return;
if (Block.EndExchange)
return;
if (!Block.PowTxTree)
return;
var CurTime = Date.now();
var ArrNodesArr = [];
var it = Block.PowTxTree.iterator(), Tr;
while ((Tr = it.next()) !== null) {
if (!Tr.IsTx) {
if (!Tr.LastProcessTime)
throw "!Tr.LastProcessTime";
var Delta = CurTime - Tr.LastProcessTime;
if (Delta >= TX_PROCESS_TIME) {
for (var i = 0; i < Tr.Nodes.length; i++) {
var TrNode = Tr.Nodes[i];
var LocDelta = CurTime - TrNode.Time;
if (!TrNode.WasSend && LocDelta >= TX_PROCESS_TIME) {
var FindArr = undefined;
for (var n = 0; n < ArrNodesArr.length; n++) {
var ElArr = ArrNodesArr[n];
if (ElArr.Node === TrNode.Node) {
FindArr = ElArr
break;
}
}
if (!FindArr) {
FindArr = { Node: TrNode.Node, Arr: [] }
ArrNodesArr.push(FindArr)
}
Tr.LastProcessTime = CurTime
TrNode.WasSend = 1
FindArr.Arr.push(Tr)
break;
}
}
}
}
}
for (var n = 0; n < ArrNodesArr.length; n++) {
var ElArr = ArrNodesArr[n];
if (global.DoTxLog)
global.ToLog("CheckTxExchange BlockNum:" + Block.BlockNum + " Array=" + ElArr.Arr.length + " to " + global.NodeName(ElArr.Node))
var SendData = { "Method": "GETTRANSFERTX", "Context": {}, "Data": { BlockNum: Block.BlockNum, TicketArray: ElArr.Arr, } };
this.SendF(ElArr.Node, SendData, ElArr.Arr.length * global.TR_TICKET_HASH_LENGTH + 1000)
}
}
GetMaxSumListFromID(Node, MaxSumID, BlockList) {
var Str0 = "GETBL:" + Node.id;
for (var i = 0; i < BlockList.length; i++) {
var elemBlockList = BlockList[i];
global.TreeBlockBuf.SaveValue(Str0 + elemBlockList.ID, elemBlockList)
}
var MaxSum = [];
MaxSum:
for (var i = 0; i < MaxSumID.length; i++) {
var elem = MaxSumID[i];
var Arr = [];
for (var n = 0; n < elem.SumListID.length; n++) {
var elemBlockList = global.TreeBlockBuf.LoadValue(Str0 + elem.SumListID[n], 1);
if (elemBlockList === undefined) {
continue MaxSum;
}
Arr.push(elemBlockList)
}
elem.SumList = Arr
MaxSum.push(elem)
}
return MaxSum;
}
CreateTransferBuffer(ArrT, MaxPOWList, MaxSumList, Block, Node) {
var Data;
var MaxSumID = [];
var BlockList = [];
for (var i = 0; i < MaxSumList.length; i++) {
var elem0 = MaxSumList[i];
var ArrID = [];
for (var n = 0; n < elem0.SumList.length; n++) {
var elemBlockList = elem0.SumList[n];
var Str = "BL:" + Node.id + global.GetHexFromArr(elemBlockList.Hash3);
var ID = global.TreeBlockBuf.LoadValue(Str, 1);
if (ID === undefined) {
this.SendBlockID++
ID = this.SendBlockID % 65535
global.TreeBlockBuf.SaveValue(Str, ID)
elemBlockList.ID = ID
BlockList.push(elemBlockList)
}
ArrID.push(ID)
}
MaxSumID.push({ BlockNum: elem0.BlockNum, SumHash: elem0.SumHash, SumListID: ArrID })
}
var ArrTt, ArrTx;
if (global.USE_TICKET) {
ArrTt = ArrT
ArrTx = []
}
else {
ArrTt = []
ArrTx = ArrT
}
Data = {
"Version": 5, "BlockNum": Block.BlockNum, "Reserv1": 0, "MaxPOW": MaxPOWList, "Reserv2": 0, "BaseBlockNum": this.CurrentBlockNum - Block.BlockNum,
"MaxSumID": MaxSumID, "BlockList": BlockList, "TicketArray": ArrTt, "TxArray": ArrTx, "NoSendTx": Node.NoSendTx,
}
var BufWrite = global.BufLib.GetBufferFromObject(Data, FORMAT_DATA_TRANSFER, global.MAX_BLOCK_SIZE + 30000, WorkStructSend);
return BufWrite;
}
static TRANSFER_F() {
return FORMAT_DATA_TRANSFER;
}
CheckingMaxPowOther(Block) {
var POW = Block.MaxPOW;
if (POW && POW.Hash && global.CompareArr(POW.PowHash, Block.PowHash) < 0) {
var LoadBlockNum = Block.BlockNum;
var LoadHash = POW.Hash;
var StrKey = this.GetStrFromHashShort(LoadHash);
var StrHashWas = this.GetStrFromHashShort(Block.Hash);
this.StartLoadBlockHeader(LoadHash, LoadBlockNum, "START OTHER:" + StrKey + " WAS:" + StrHashWas, false)
global.AddInfoBlock(Block, "REQ H: " + StrKey)
}
Block.CheckMaxPow = true
}
AddToMaxPOW(Block, item, Node?) {
if (Block && item) {
if (!Block.MaxPOW)
Block.MaxPOW = {}
var POW = Block.MaxPOW;
if (!Block.PrevHash)
return;
item.BlockNum = Block.BlockNum
item.PrevHash = Block.PrevHash
global.CalcHashBlockFromSeqAddr(item, Block.PrevHash, global.MINING_VERSION_NUM)
if (POW.SeqHash === undefined || global.CompareArr(item.PowHash, POW.PowHash) < 0) {
POW.AddrHash = item.AddrHash
POW.Hash = item.Hash
POW.PowHash = item.PowHash
POW.PrevHash = item.PrevHash
POW.TreeHash = item.TreeHash
POW.SeqHash = item.SeqHash
}
if (Block.SeqHash && global.CompareArr(item.SeqHash, Block.SeqHash) === 0) {
if (POW.LocalSeqHash === undefined || global.CompareArr(POW.LocalSeqHash, Block.SeqHash) !== 0 || global.CompareArr(item.PowHash, POW.PowLocalHash) < 0) {
POW.LocalAddrHash = item.AddrHash
POW.PowLocalHash = item.PowHash
POW.LocalSeqHash = Block.SeqHash
}
}
var wasLider;
if (POW.MaxTree)
wasLider = POW.MaxTree.min()
this.AddPOWToMaxTree(POW, item)
if (wasLider) {
var newLider = POW.MaxTree.min();
if (newLider !== wasLider) {
var Power = global.GetPowPower(newLider.PowHash);
global.AddInfoBlock(Block, "MaxPOW: " + Power)
}
}
}
}
AddPOWToMaxTree(POW, item) {
if (!POW.MaxTree) {
POW.MaxTree = new RBTree(function(a: any, b: any) {
return global.CompareArr(a.PowHash, b.PowHash);
})
}
if (!POW.MaxTree.find(item)) {
POW.MaxTree.insert(item)
if (POW.MaxTree.size > 12) {
var maxitem = POW.MaxTree.max();
POW.MaxTree.remove(maxitem)
}
}
}
GetMaxPOWList() {
var arr = [];
var start, finish;
start = this.CurrentBlockNum + global.TIME_START_SAVE - 2
finish = this.CurrentBlockNum
for (var b = start; b < finish; b++) {
var Block = this.GetBlock(b);
if (Block && Block.Prepared && Block.MaxPOW) {
if (Block.MaxPOW && Block.MaxPOW.MaxTree) {
this.RecreateMaxPOW(Block)
var it = Block.MaxPOW.MaxTree.iterator(), Item;
while ((Item = it.next()) !== null) {
arr.push(Item)
}
}
}
}
return arr;
}
ToMaxPOWList(Arr) {
for (var i = 0; i < Arr.length; i++) {
var item = Arr[i];
if (item && item.BlockNum >= this.CurrentBlockNum - global.BLOCK_PROCESSING_LENGTH && item.BlockNum < this.CurrentBlockNum) {
var Block = this.GetBlock(item.BlockNum);
this.AddToMaxPOW(Block, item)
}
}
}
RecreateMaxPOW(Block) {
if (Block.MaxPOW && Block.MaxPOW.MaxTree) {
var Tree = Block.MaxPOW.MaxTree;
var it = Tree.iterator(), Item;
while ((Item = it.next()) !== null) {
if (!Item.PrevHash)
global.ToLog("NO Item.PrevHash in " + Block.BlockNum)
if (Item.PrevHash && global.CompareArr(Item.PrevHash, Block.PrevHash) !== 0) {
Tree.remove(Item)
it = Tree.iterator()
}
}
}
Block.CheckMaxSum = false
}
CheckMaxSum(Block) {
var POW = Block.MaxSum;
var List = this.GetBlockList(Block.BlockNum);
var SumPow = this.GetSumFromList(List, Block.BlockNum);
if (POW && POW.SumHash && POW.SumPow > SumPow) {
var LoadBlockNum = Block.BlockNum;
var LoadHash = POW.SumHash;
var StrKey = this.GetStrFromHashShort(LoadHash);
if (this.StartLoadBlockHeader(LoadHash, LoadBlockNum, "START POW:" + POW.SumPow + ">" + SumPow + " SH:" + StrKey, true))
global.AddInfoBlock(Block, "REQ SH: " + StrKey)
}
Block.CheckMaxSum = true
}
AddToMaxSum(Block, item) {
if (Block && item) {
if (!Block.MaxSum)
Block.MaxSum = {}
var POW = Block.MaxSum;
var SumPow = this.GetSumFromList(item.SumList, Block.BlockNum);
if (POW.SumHash === undefined || SumPow > POW.SumPow) {
POW.SumPow = SumPow
POW.SumHash = item.SumHash
POW.SumList = item.SumList
global.AddInfoBlock(Block, "SumPow:" + POW.SumPow)
Block.CheckMaxSum = false
}
return SumPow;
}
return 0;
}
GetMaxSumList() {
var Arr = [];
var start, finish;
start = this.CurrentBlockNum + global.TIME_START_LOAD - 2
finish = this.CurrentBlockNum
for (var b = start; b <= finish; b++) {
var Block = this.GetBlock(b);
if (Block && Block.bSave && Block.MaxSum && Block.MaxSum.SumHash) {
var POW = Block.MaxSum;
var item = { BlockNum: Block.BlockNum, SumHash: POW.SumHash, SumList: POW.SumList, };
Arr.push(item)
}
}
return Arr;
}
ToMaxSumList(Arr) {
var start, finish;
start = this.CurrentBlockNum + global.TIME_START_LOAD - 2
finish = this.CurrentBlockNum
for (var i = 0; i < Arr.length; i++) {
var item = Arr[i];
if (item && item.BlockNum >= start && item.BlockNum <= finish) {
var Block = this.GetBlock(item.BlockNum);
if (Block) {
this.AddToMaxSum(Block, item)
this.CheckMaxSum(Block)
}
}
}
}
GetBlockList(CurBlockNum) {
var arr = [];
for (var b = CurBlockNum - global.SUM_LIST_LENGTH + 1; b <= CurBlockNum; b++) {
var Block = this.GetBlock(b);
if (Block && Block.bSave) {
var item = { AddrHash: Block.AddrHash, SeqHash: Block.SeqHash, };
arr.push(item)
}
else {
return [];
}
}
return arr;
}
GetSumFromList(arr, CurBlockNum) {
var SumPow = 0;
if (arr.length !== global.SUM_LIST_LENGTH)
return SumPow;
var CountLoad = 0;
var BlockNumStart = CurBlockNum - arr.length + 1;
for (var i = 0; i < arr.length; i++) {
var Item = arr[i];
if (Item) {
Item.BlockNum = BlockNumStart + i
var Value = global.GetHashFromSeqAddr(Item.SeqHash, Item.AddrHash, Item.BlockNum, undefined, global.MINING_VERSION_NUM);
SumPow += global.GetPowPower(Value.PowHash)
Item.Hash3 = Value.Hash
}
else {
break;
}
}
return SumPow;
}
GetArrayFromTxTree(Block) {
if (!Block.PowTxTree)
return [];
var BufLength = 0;
var arr = [];
var it = Block.PowTxTree.iterator(), Item;
while ((Item = it.next()) !== null) {
arr.push(Item)
BufLength += Item.body.length
if (BufLength > global.MAX_BLOCK_SIZE)
break;
}
return arr;
}
GetArrayFromTicketTree(Block) {
if (!Block.PowTicketTree)
return [];
var arr = [];
var it = Block.PowTicketTree.iterator(), Item;
while ((Item = it.next()) !== null) {
arr.push(Item)
}
return arr;
}
CheckPrioritetTx(Tr) {
if (Tr.Prioritet === undefined) {
var Body = Tr.body;
Tr.Prioritet = global.MAX_LENGTH_SENDER_MAP
var App = global.DAppByType[Body[0]];
if (App) {
Tr.SenderNum = App.GetSenderNum(Tr.num, Body)
if (Tr.SenderNum && Tr.SenderNum > 0) {
Tr.Prioritet = this.GetSenderPrioritet(Tr.num, Tr.SenderNum)
Tr.TimePow = Tr.Prioritet + Tr.power
}
}
}
}
GetSenderPrioritet(BlockNum, SenderNum) {
//defiend in transaction-validator.ts(CSmartContract)
}
AddToQuote(Tree, Tr) {
this.CheckPrioritetTx(Tr)
var Tr0 = Tree.find(Tr);
if (Tr0) {
return 3;
}
else {
Tree.insert(Tr)
if (Tree.size > global.MAX_TRANSACTION_LIMIT) {
var maxitem = Tree.max();
Tree.remove(maxitem)
if (global.CompareArr(maxitem.HashPow, Tr.HashPow) === 0)
return 0;
}
return 1;
}
}
IsValidTicket(Tr, BlockNum): any {
// defiend in transaction-validator.ts(CSmartContract)
}
IsValidTransaction(Tr, BlockNum): any {
// defiend in transaction-validator.ts(CSmartContract)
}
AddDAppTransactions(BlockNum, Arr) {
// defiend in transaction-validator.ts(CSmartContract)
}
AddTicketToBlockQuote(Block, Tr) {
if (Block.PowTicketTree) {
var Res = this.IsValidTicket(Tr, Block.BlockNum);
if (Res >= 1) {
Res = this.AddToQuote(Block.PowTicketTree, Tr)
if (Res)
return Block.PowTicketTree.find(Tr);
}
return null;
}
}
AddTrToBlockQuote(Block, Tr, bTTAdd?) {
if (Block.PowTxTree) {
var Res = this.IsValidTransaction(Tr, Block.BlockNum);
if (Res >= 1) {
if (bTTAdd) {
Res = this.AddToQuote(Block.PowTicketTree, Tr)
if (Res <= 0)
return Res;
}
Res = this.AddToQuote(Block.PowTxTree, Tr)
}
return Res;
}
}
GetBlockContext(BlockNum) {
if (BlockNum === undefined || !this.IsCorrectBlockNum(BlockNum))
return undefined;
var Context = this.GetBlock(BlockNum);
if (!Context || !Context.StartTimeNum) {
Context = this.CreateBlockContext()
Context.BlockNum = BlockNum
Context.DELTA_CURRENT_TIME = global.GetDeltaCurrentTime()
Context.StartTimeNum = (BlockNum - 1 + global.BLOCK_DELTA_ACTIVATE) * global.CONSENSUS_PERIOD_TIME + global.START_NETWORK_DATE
this.BlockChain[BlockNum] = Context
}
if (!Context.TransferFromAddr) {
Context.TransferFromAddr = {}
Context.LevelsTransfer = []
}
return Context;
}
StartBlock(Block) {
Block.Active = true
}
IsCorrectBlockNum(BlockNum) {
var start = this.CurrentBlockNum - global.BLOCK_PROCESSING_LENGTH;
var finish = this.GetLastCorrectBlockNum();
if (BlockNum < start || BlockNum > finish) {
return false;
}
return true;
}
GetLastCorrectBlockNum() {
return this.CurrentBlockNum + 4;
}
GetStrSendCount(Block) {
if (!Block)
return "";
var Str = "";
var Count = 0;
for (var L = 0; L < Block.LevelsTransfer.length; L++) {
var Transfer = Block.LevelsTransfer[L];
Str = Str + "," + Transfer.SendCount
if (typeof Transfer.SendCount === "number")
Count = Count + Transfer.SendCount
}
return "" + Count + ":[" + Str.substr(1) + "]";
}
GetStrGetCount(Block) {
if (!Block)
return "";
var Str = "";
var Count = 0;
for (var L = 0; L < Block.LevelsTransfer.length; L++) {
var Transfer = Block.LevelsTransfer[L];
Str = Str + "," + Transfer.GetCount
Count = Count + Transfer.GetCount
}
return "" + Count + ":[" + Str.substr(1) + "]";
}
ToStrBlocks(DopStr) {
var num = Math.floor(this.CurrentBlockNum / 3) * 3;
var start = num - global.BLOCK_PROCESSING_LENGTH2 + 2;
var finish = this.CurrentBlockNum;
if (!DopStr)
DopStr = ""
var Str = "";
for (var b = start; b <= finish; b++) {
var hashStr = "";
var Block = this.GetBlock(b);
if (Block && Block.ErrRun) {
if (Block.ErrRun)
hashStr = Block.ErrRun.substr(0, 5)
else
if (Block && Block.TreeHash)
hashStr = "-" + global.GetHexFromAddres(Block.TreeHash).substr(0, 3) + "-"
}
else
if (Block && Block.TreeHash) {
hashStr = global.GetHexFromAddres(Block.TreeHash).substr(0, 5)
}
Str = Str + "|" + (hashStr + " ").substr(0, 5)
}
Str = Str.substr(1)
global.ToInfo("" + finish + " -> " + Str + " " + DopStr)
}
PreparePOWHash(Block) {
if (!Block.TreeHash)
Block.TreeHash = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
var PrevHash = this.GetPrevHash(Block);
if (!PrevHash) {
global.AddInfoBlock(Block, "-err prev hash-")
return false;
}
Block.PrevHash = PrevHash
Block.SeqHash = this.GetSeqHash(Block.BlockNum, Block.PrevHash, Block.TreeHash)
this.CreatePOWNew(Block)
Block.Prepared = true
if (global.USE_MINING && !Block.StartMining) {
Block.StartMining = true
global.AddInfoBlock(Block, "-send mining-")
global.SetCalcPOW(Block, "FastCalcBlock")
}
return true;
}
CalcTreeHashFromArrTr(BlockNum, arrTr) {
var arrHASH = [];
for (var i = 0; i < arrTr.length; i++) {
var Tr = arrTr[i];
arrHASH.push(Tr.HASH)
}
var Tree = global.CalcMerklFromArray(BlockNum, arrHASH);
return Tree.Root;
}
CreateTreeHash(Block) {
if (Block.EndExchange)
return;
Block.EndExchange = true
if (Block.bSave)
return;
var PrevBlock = this.GetBlock(Block.BlockNum - 1);
if (PrevBlock && !PrevBlock.EndExchange && !PrevBlock.bSave) {
global.AddInfoBlock(Block, "Prev Not End Exchange")
return;
}
global.AddInfoBlock(Block, "End Exchange,N=" + Block.TransferNodesCount)
var arrContent = [];
var arrHASH = [];
var arrTr = this.GetArrayFromTxTree(Block);
this.AddDAppTransactions(Block.BlockNum, arrTr)
for (var i = 0; i < arrTr.length; i++) {
var Tr = arrTr[i];
arrContent.push(Tr.body)
arrHASH.push(Tr.HASH)
}
var Tree = global.CalcMerklFromArray(Block.BlockNum, arrHASH);
Block.TreeHash = Tree.Root
Block.arrContent = arrContent
Block.TrCount = Block.arrContent.length
}
WatchdogSaved(BlockNum) {
var Block = this.GetBlock(BlockNum);
if (!Block) {
global.ToLog("#1 WatchdogSaved: no BlockNum=" + BlockNum)
return;
}
if (Block.bSave) {
var BlockDB = this.ReadBlockDB(BlockNum);
if (!BlockDB) {
Block.bSave = false
return;
}
if (global.CompareArr(BlockDB.Hash, Block.Hash) !== 0) {
global.AddInfoBlock(Block, "=ERR:WATCHDOG=")
global.ToLog("#3 WatchdogSaved: Error Hash on Num=" + BlockNum)
return;
}
if (global.CompareArr(BlockDB.SumHash, Block.SumHash) !== 0) {
global.AddInfoBlock(Block, "=ERR:WATCHDOG=")
global.ToLog("#4 WatchdogSaved: Error SumHash on Num=" + BlockNum)
return;
}
if (global.CompareArr(BlockDB.SeqHash, Block.SeqHash) !== 0) {
global.AddInfoBlock(Block, "=ERR:WATCHDOG=")
global.ToLog("#5 WatchdogSaved: Error SeqHash on Num=" + BlockNum)
return;
}
var PrevHash = this.GetPrevHash(Block);
if (!PrevHash) {
global.AddInfoBlock(Block, "=ERR:WATCHDOG=")
global.ToLog("#6 WatchdogSaved: Error PrevHash on Num=" + BlockNum)
return;
}
var SeqHash = this.GetSeqHash(Block.BlockNum, PrevHash, Block.TreeHash);
if (global.CompareArr(SeqHash, Block.SeqHash) !== 0) {
global.AddInfoBlock(Block, "=ERR:WATCHDOG=")
global.ToLog("#7 WatchdogSaved: Error SeqHash on Num=" + BlockNum)
return;
}
PrevHash = this.GetPrevHashDB(BlockDB)
SeqHash = this.GetSeqHash(BlockDB.BlockNum, PrevHash, BlockDB.TreeHash)
if (global.CompareArr(SeqHash, BlockDB.SeqHash) !== 0) {
global.AddInfoBlock(Block, "=ERR:WATCHDOG=")
global.ToLog("#8 WatchdogSaved: Error SeqHash on Num=" + BlockNum)
return;
}
}
}
DoBlockChain() {
if (global.glStopNode)
return;
if (!global.CAN_START)
return;
this.StartConsensus()
var CURRENTBLOCKNUM = this.CurrentBlockNum;
if (global.GrayConnect()) {
if (!this.LoadHistoryMode)
this.StartSyncBlockchain(undefined, 1)
return;
}
if (this.LoadHistoryMode)
return;
var bWasSave = false;
var LoadBlockNum;
var LoadHash;
var start_save = CURRENTBLOCKNUM + global.TIME_START_SAVE;
for (var BlockNum = CURRENTBLOCKNUM - global.BLOCK_PROCESSING_LENGTH2; BlockNum > global.BLOCK_PROCESSING_LENGTH2 && BlockNum < CURRENTBLOCKNUM; BlockNum++) {
var Block = this.GetBlock(BlockNum);
if (!Block) {
Block = this.GetBlockContext(BlockNum)
if (!Block) {
continue;
}
}
if (Block.bSave) {
var BlockDB = this.ReadBlockDB(BlockNum);
if (!BlockDB) {
Block.bSave = false
}
}
if (global.WATCHDOG_DEV)
this.WatchdogSaved(Block.BlockNum)
if (Block.bSave) {
bWasSave = true
if (Block.MaxSum && !Block.CheckMaxSum) {
global.AddInfoBlock(Block, "CheckMaxSum")
this.CheckMaxSum(Block)
}
if (BlockNum <= CURRENTBLOCKNUM - global.BLOCK_PROCESSING_LENGTH * 4) {
Block.TransferFromAddr = undefined
Block.LevelsTransfer = undefined
Block.mapData = undefined
Block.MaxPOW = undefined
Block.MaxSum = undefined
Block.arrContent = undefined
if (Block.PowTxTree) {
Block.PowTxTree.clear()
Block.PowTxTree = undefined
}
}
continue;
}
var PrevBlock = this.GetBlock(BlockNum - 1);
if (!PrevBlock) {
Block.HasErr = 1
global.AddInfoBlock(Block, "!PrevBlock")
continue;
}
if (BlockNum >= CURRENTBLOCKNUM + global.TIME_END_EXCHANGE) {
if (!Block.Active) {
global.AddInfoBlock(Block, "WAIT ACTIVATE")
continue;
}
else
if (!Block.EndExchange) {
global.AddInfoBlock(Block, "WAIT EXCHANGE")
continue;
}
}
if (BlockNum === CURRENTBLOCKNUM + global.TIME_START_POW || Block.EndExchange)
if (!Block.Prepared) {
if (!Block.EndExchange)
this.CreateTreeHash(Block)
global.AddInfoBlock(Block, "Start POW")
this.PreparePOWHash(Block)
if (!Block.Prepared)
global.AddInfoBlock(Block, "!!Prepared")
continue;
}
if (!Block.EndExchange) {
global.AddInfoBlock(Block, "Not EndExchange")
Block.HasErr = 1
Block.Prepared = 0
this.CreateTreeHash(Block)
}
if (!Block.Prepared) {
Block.HasErr = 1
global.AddInfoBlock(Block, "Not was Prepared")
this.PreparePOWHash(Block)
if (!Block.Prepared)
continue;
}
{
var PrevHash = this.GetPrevHash(Block);
if (!PrevHash) {
Block.HasErr = 1
continue;
}
var SeqHash = this.GetSeqHash(Block.BlockNum, PrevHash, Block.TreeHash);
if (global.CompareArr(SeqHash, Block.SeqHash) !== 0) {
Block.HasErr = 1
global.AddInfoBlock(Block, "New fast pow")
this.PreparePOWHash(Block)
}
if (Block.MaxPOW && Block.MaxPOW.SeqHash && Block.MaxPOW.AddrHash && Block.MaxPOW.LocalSeqHash && global.CompareArr(Block.SeqHash,
Block.MaxPOW.LocalSeqHash) === 0) {
if (global.CompareArr(Block.SeqHash, Block.MaxPOW.LocalSeqHash) === 0 && global.CompareArr(Block.MaxPOW.PowLocalHash, Block.PowHash) < 0) {
Block.AddrHash = Block.MaxPOW.LocalAddrHash
global.CalcHashBlockFromSeqAddr(Block, Block.PrevHash, global.MINING_VERSION_NUM)
global.AddInfoBlock(Block, "->Local lider:" + global.GetPowPower(Block.PowHash))
}
if (global.CompareArr(Block.SeqHash, Block.MaxPOW.SeqHash) === 0 && global.CompareArr(Block.MaxPOW.AddrHash, Block.AddrHash) !== 0 && global.CompareArr(Block.MaxPOW.PowHash,
Block.PowHash) < 0) {
Block.AddrHash = Block.MaxPOW.AddrHash
global.CalcHashBlockFromSeqAddr(Block, Block.PrevHash, global.MINING_VERSION_NUM)
global.AddInfoBlock(Block, "->Max lider")
}
}
else {
Block.HasErr = 1
global.AddInfoBlock(Block, "ERROR MaxPOW")
}
if (Block.MaxPOW && Block.MaxPOW.SeqHash && !Block.CheckMaxPow && !Block.CheckMaxSum && global.CompareArr(Block.SeqHash, Block.MaxPOW.SeqHash) !== 0) {
global.AddInfoBlock(Block, "CheckMaxPow")
this.CheckingMaxPowOther(Block)
}
if (BlockNum > start_save)
continue;
if (PrevBlock.bSave && this.BlockNumDB + 1 >= Block.BlockNum) {
this.AddToStatBlockConfirmation(Block)
var Power = global.GetPowPower(Block.PowHash);
if (this.WriteBlockDB(Block)) {
if (Block.arrContent && Block.arrContent.length)
global.ADD_TO_STAT("MAX:TRANSACTION_COUNT", Block.arrContent.length)
global.AddInfoBlock(Block, "SAVE:" + Power + " TH:" + this.GetStrFromHashShort(Block.TreeHash).substr(0, 4))
}
else {
Block.HasErr = 1
global.AddInfoBlock(Block, "ERROR WRITE DB")
}
this.AddToMaxSum(Block, { SumHash: Block.SumHash, SumList: this.GetBlockList(Block.BlockNum), })
if (typeof global.RESYNC_CONDITION === "object") {
if (!this.OwnBlockCount)
this.OwnBlockCount = 0
var Miner = global.ReadUintFromArr(Block.AddrHash, 0);
var MultK = global.RESYNC_CONDITION.K_POW;
var MaxBlocks = global.RESYNC_CONDITION.OWN_BLOCKS;
if (Miner === global.GENERATE_BLOCK_ACCOUNT) {
this.OwnBlockCount++
if (this.OwnBlockCount >= MaxBlocks) {
var PrevSumPow = this.GetAvgPowBlock(Block.BlockNum - 2 * MaxBlocks, MaxBlocks);
var CurrentPow = this.GetAvgPowBlock(Block.BlockNum - MaxBlocks, MaxBlocks);
if (CurrentPow === 0 || PrevSumPow - CurrentPow >= MultK) {
global.ToLog("START RESYNC CONDITION")
this.OwnBlockCount = 0
this.StartSyncBlockchain()
return;
}
}
} else {
this.OwnBlockCount = 0
}
}
} else {
Block.HasErr = 1
if (!PrevBlock.bSave)
global.AddInfoBlock(Block, "Prev block not saved")
else
global.AddInfoBlock(Block, "Low BlockNumDB")
}
}
}
var MaxNumBlockDB = this.GetMaxNumBlockDB();
if (CURRENTBLOCKNUM + global.BLOCK_PROCESSING_LENGTH2 > MaxNumBlockDB && CURRENTBLOCKNUM - global.BLOCK_PROCESSING_LENGTH2 < MaxNumBlockDB)
for (var BlockNum = CURRENTBLOCKNUM - global.BLOCK_PROCESSING_LENGTH2; BlockNum > global.BLOCK_PROCESSING_LENGTH2 && BlockNum < start_save; BlockNum++) {
var Block = this.GetBlock(BlockNum);
if (Block && !Block.bSave && Block.TrCount && Block.TreeHash && !global.IsZeroArr(Block.TreeHash) && !Block.WasSaveDataTree) {
this.PreSaveDataTreeToDB(Block)
Block.WasSaveDataTree = 1
global.AddInfoBlock(Block, "*PRESAVE DATA TREE*")
global.ToLog("PRESAVE DATA: " + Block.BlockNum, 2)
}
}
this.RelayMode = !bWasSave
this.FREE_MEM_BLOCKS(CURRENTBLOCKNUM - global.BLOCK_COUNT_IN_MEMORY)
}
GetAvgPowBlock(StartNum, CountNum) {
var Count = 0;
var SumPow = 0;
for (var Num = StartNum; Num < StartNum + CountNum; Num++) {
var Block = this.GetBlock(Num);
if (Block && Block.bSave) {
var Power = global.GetPowPower(Block.PowHash);
SumPow += Power
Count++
}
}
if (!Count)
return 0;
else
return SumPow / Count;
}
CreatePOWNew(Block) {
global.CreateHashMinimal(Block, global.GENERATE_BLOCK_ACCOUNT)
this.AddToMaxPOW(Block, {
SeqHash: Block.SeqHash, AddrHash: Block.AddrHash, PrevHash: Block.PrevHash, TreeHash: Block.TreeHash,
})
}
SetNoPOW(BlockNumFrom, bReload, RefBlockNum) {
var CurNum = BlockNumFrom;
var finish = this.GetLastCorrectBlockNum();
while (true) {
var BlockMem = this.BlockChain[CurNum];
if (BlockMem) {
if (BlockMem.Prepared) {
global.AddInfoBlock(BlockMem, "-reset POW:" + RefBlockNum + "/" + bReload)
BlockMem.bSave = false
BlockMem.Prepared = false
BlockMem.StartMining = false
this.PreparePOWHash(BlockMem)
}
this.RecreateMaxPOW(BlockMem)
}
if (!BlockMem && CurNum > finish)
break;
CurNum++
}
}
MiningProcess(msg) {
var BlockMining = this.GetBlock(msg.BlockNum);
if (!BlockMining) {
teraManager.SendToWebClient({
msg: msg,
error: '!BlockMining'
})
return;
}
if (!BlockMining.StartMining || BlockMining.bSave) {
teraManager.SendToWebClient({
msg: msg,
error: `!BlockMining.StartMining ${BlockMining.StartMining} || BlockMining.bSave ${BlockMining.bSave}`
})
return;
}
if (BlockMining && BlockMining.Hash && BlockMining.SeqHash && global.CompareArr(BlockMining.SeqHash, msg.SeqHash) === 0) {
var ValueOld = global.GetHashFromSeqAddr(BlockMining.SeqHash, BlockMining.AddrHash, BlockMining.BlockNum);
var ValueMsg = global.GetHashFromSeqAddr(msg.SeqHash, msg.AddrHash, BlockMining.BlockNum);
var bWas = 0;
if (global.CompareArr(ValueOld.Hash1, ValueMsg.Hash1) > 0) {
var Nonce1 = global.ReadUintFromArr(msg.AddrHash, 12);
var DeltaNum1 = global.ReadUint16FromArr(msg.AddrHash, 24);
global.WriteUintToArrOnPos(BlockMining.AddrHash, Nonce1, 12)
global.WriteUint16ToArrOnPos(BlockMining.AddrHash, DeltaNum1, 24)
bWas += 1
}
if (global.CompareArr(ValueOld.Hash2, ValueMsg.Hash2) > 0) {
var Nonce0 = global.ReadUintFromArr(msg.AddrHash, 6);
var Nonce2 = global.ReadUintFromArr(msg.AddrHash, 18);
var DeltaNum2 = global.ReadUint16FromArr(msg.AddrHash, 26);
global.WriteUintToArrOnPos(BlockMining.AddrHash, Nonce0, 6)
global.WriteUintToArrOnPos(BlockMining.AddrHash, Nonce2, 18)
global.WriteUint16ToArrOnPos(BlockMining.AddrHash, DeltaNum2, 26)
bWas += 2
}
if (!bWas)
return;
var ValueNew = global.GetHashFromSeqAddr(BlockMining.SeqHash, BlockMining.AddrHash, BlockMining.BlockNum);
BlockMining.Hash = ValueNew.Hash
BlockMining.PowHash = ValueNew.PowHash
BlockMining.Power = global.GetPowPower(BlockMining.PowHash)
global.ADD_TO_STAT("MAX:POWER", BlockMining.Power)
var Power = global.GetPowPower(BlockMining.PowHash);
var HashCount = Math.pow(2, Power);
global.ADD_HASH_RATE(HashCount)
global.AddInfoBlock(BlockMining, "Set POW: " + Power)
this.SetNoPOW(BlockMining.BlockNum + 8, 0, BlockMining.BlockNum)
this.AddToMaxPOW(BlockMining, {
SeqHash: BlockMining.SeqHash, AddrHash: BlockMining.AddrHash, PrevHash: BlockMining.PrevHash, TreeHash: BlockMining.TreeHash,
})
if (bWas == 3) {
setTimeout(() => {
let webmsg: any = { BlockNum: msg.BlockNum }
webmsg.Mining = {
SeqHash: global.GetHexFromArr(BlockMining.SeqHash),
AddrHash: global.GetHexFromArr(BlockMining.AddrHash),
PrevHash: global.GetHexFromArr(BlockMining.PrevHash),
TreeHash: global.GetHexFromArr(BlockMining.TreeHash),
Hash: global.GetHexFromArr(BlockMining.Hash),
PowHash: global.GetHexFromArr(BlockMining.PowHash)
}
Object.assign(webmsg, {
HashCount,
Power,
Num: msg.NodeNum
})
teraManager.SendToWebClient(webmsg)
}, 1)
}
}
}
};
global.TreeBlockBuf = new STreeBuffer(50 * 1000, global.CompareItemHashSimple, "string");
var PrevTimeIdle = 0;
OnTimeIdle();
function OnTimeIdle() {
var CurTime = Date.now();
var Delta = CurTime - PrevTimeIdle;
if (Delta <= 51) {
global.ADD_TO_STAT("TIME_IDLE", 5);
}
setTimeout(OnTimeIdle, 49);
PrevTimeIdle = CurTime;
};