40
src/core/api/api-exchange.ts
Normal file
40
src/core/api/api-exchange.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
|
||||
*/
|
||||
import * as crypto from 'crypto'
|
||||
global.HTTPCaller.CreateAccount = function(Params, response) {
|
||||
if (typeof Params === "object" && Params.Name && Params.PubKey) {
|
||||
var TYPE_TRANSACTION_CREATE = 100;
|
||||
var TR = {
|
||||
Type: global.TYPE_TRANSACTION_CREATE, Currency: Params.Currency, PubKey: global.GetArrFromHex(Params.PubKey), Description: Params.Name,
|
||||
Smart: Params.Smart, Adviser: 0,
|
||||
};
|
||||
var Body = global.BufLib.GetBufferFromObject(TR, global.global.FORMAT_CREATE, 1000, {});
|
||||
return { result: 1 };
|
||||
}
|
||||
return { result: 0 };
|
||||
};
|
||||
var MaxCountViewRows = global.HTTP_MAX_COUNT_ROWS;
|
||||
global.HTTPCaller.GetBalance = function(Params) {
|
||||
if (typeof Params === "object") {
|
||||
var arr = global.DApps.Accounts.GetRowsAccounts(ParseNum(Params.AccountID), 1);
|
||||
if (arr.length) {
|
||||
arr[0].result = 1;
|
||||
return arr[0];
|
||||
}
|
||||
}
|
||||
return { result: 0 };
|
||||
};
|
||||
global.HTTPCaller.GenerateKeys = function(Params) {
|
||||
var KeyPair = crypto.createECDH('secp256k1');
|
||||
var PrivKey = global.sha3(crypto.randomBytes(32));
|
||||
KeyPair.setPrivateKey(Buffer.from(PrivKey));
|
||||
var PubKey = KeyPair.getPublicKey('' as any, 'compressed');
|
||||
return { result: 1, PrivKey: global.GetHexFromArr(PrivKey), PubKey: global.GetHexFromArr(PubKey) };
|
||||
};
|
||||
10
src/core/api/api-wallet.ts
Normal file
10
src/core/api/api-wallet.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
|
||||
*/
|
||||
|
||||
390
src/core/base.ts
Normal file
390
src/core/base.ts
Normal file
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* @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";
|
||||
require("./library.js");
|
||||
require("./crypto-library");
|
||||
require("./terahashmining");
|
||||
import * as crypto from 'crypto';
|
||||
const os = require('os');
|
||||
global.glStopNode = false;
|
||||
const MAX_TIME_NETWORK_TRANSPORT = 1 * 1000;
|
||||
var GlSumUser;
|
||||
var GlSumSys;
|
||||
var GlSumIdle;
|
||||
global.CountAllNode = 0;
|
||||
module.exports = class CCommon importasdasd {
|
||||
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
|
||||
global.SERVER = this
|
||||
this.VirtualMode = bVirtual
|
||||
this.KeyPair = SetKeyPair
|
||||
var PubKey = SetKeyPair.getPublicKey('', 'compressed');
|
||||
this.PubKeyType = PubKey[0]
|
||||
this.addrArr = PubKey.slice(1)
|
||||
this.addrStr = global.GetHexFromArr(this.addrArr)
|
||||
this.HashDBArr = shaarr2(this.KeyPair.getPrivateKey(), [0, 0, 0, 0, 0, 0, 0, 1])
|
||||
this.ServerSign = []
|
||||
}
|
||||
AddStatOnTimer() {
|
||||
var CountAll = 0;
|
||||
var CurTime = global.GetCurrentTime() - 0;
|
||||
for (var i = 0; i < this.NodesArr.length; i++) {
|
||||
var Item = this.NodesArr[i];
|
||||
if (Item.LastTime && (CurTime - Item.LastTime) < NODES_DELTA_CALC_HOUR * 3600 * 1000)
|
||||
CountAll++
|
||||
else
|
||||
if (Item.LastTimeGetNode && (CurTime - Item.LastTimeGetNode) < NODES_DELTA_CALC_HOUR * 3600 * 1000)
|
||||
CountAll++
|
||||
}
|
||||
global.CountAllNode = CountAll
|
||||
if (!global.STAT_MODE)
|
||||
return;
|
||||
var StateTX = global.DApps.Accounts.DBStateTX.Read(0);
|
||||
if (StateTX) {
|
||||
var Delta = this.CurrentBlockNum - StateTX.BlockNum;
|
||||
global.ADD_TO_STAT("MAX:DELTA_TX", Delta)
|
||||
}
|
||||
var bHasCP = 0;
|
||||
if (CHECK_POINT.BlockNum) {
|
||||
var Block = this.ReadBlockHeaderDB(CHECK_POINT.BlockNum);
|
||||
if (Block && global.CompareArr(CHECK_POINT.Hash, Block.Hash) === 0)
|
||||
bHasCP = 1
|
||||
}
|
||||
var MinVer = global.MIN_VER_STAT;
|
||||
if (MinVer === 0)
|
||||
MinVer = global.UPDATE_CODE_VERSION_NUM
|
||||
var BufMap = {}, BufMap2 = {};
|
||||
var arr = this.GetActualNodes();
|
||||
var Count = 0, CountHot = 0, CountHotOK = 0, CountActualOK = 0, SumDeltaHot = 0, SumDeltaActual = 0, CountCP = 0, CountLH = 0,
|
||||
CountHash = 0, CountVer = 0, CountStop = 0;
|
||||
var CountAutoCorrectTime = 0;
|
||||
var SumAvgDeltaTime = 0;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var Node = arr[i];
|
||||
if (!Node || Node.IsAddrList)
|
||||
continue;
|
||||
var INFO = Node.INFO;
|
||||
if (!INFO)
|
||||
INFO = {}
|
||||
if (bHasCP && CHECK_POINT.BlockNum && INFO.CheckPointHashDB && global.CompareArr(CHECK_POINT.Hash, INFO.CheckPointHashDB) === 0) {
|
||||
CountCP++
|
||||
}
|
||||
if (INFO.LoadHistoryMode)
|
||||
CountLH++
|
||||
if (Node.StopGetBlock)
|
||||
CountStop++
|
||||
Count++
|
||||
SumAvgDeltaTime += Node.DeltaGlobTime
|
||||
if (Node.VersionNum >= MinVer)
|
||||
CountVer++
|
||||
if (INFO && INFO.BlockNumDB && INFO.BlockNumDB <= this.BlockNumDB) {
|
||||
var HashDB = ReadHashFromBufDB(BufMap2, INFO.BlockNumDB);
|
||||
if (HashDB && global.CompareArr(HashDB, INFO.HashDB) === 0)
|
||||
CountHash++
|
||||
}
|
||||
var StrChk = GetCheckAccHash(BufMap, INFO.AccountBlockNum, INFO.AccountsHash);
|
||||
var Chck = 0;
|
||||
if (StrChk.indexOf("=OK=") >= 0) {
|
||||
Chck = 1
|
||||
}
|
||||
var DeltaTime = Node.DeltaTime;
|
||||
if (!DeltaTime)
|
||||
DeltaTime = 0
|
||||
CountActualOK += Chck
|
||||
SumDeltaActual += DeltaTime
|
||||
if (Node.Hot) {
|
||||
CountHot++
|
||||
CountHotOK += Chck
|
||||
SumDeltaHot += DeltaTime
|
||||
}
|
||||
if (INFO.AutoCorrectTime)
|
||||
CountAutoCorrectTime++
|
||||
}
|
||||
global.ADD_TO_STAT("MAX:ALL_NODES", CountAll)
|
||||
global.ADD_TO_STAT("MAX:CONNECTED_NODES", Count)
|
||||
global.ADD_TO_STAT("MAX:HOT_NODES", CountHot)
|
||||
global.ADD_TO_STAT("MAX:HOT_OK", CountHotOK)
|
||||
global.ADD_TO_STAT("MAX:ACTUAL_OK", CountActualOK)
|
||||
global.ADD_TO_STAT("MAX:CHECK_POINT_OK", CountCP)
|
||||
global.ADD_TO_STAT("MAX:COUNTLH", CountLH)
|
||||
global.ADD_TO_STAT("MAX:HASH_OK", CountHash)
|
||||
global.ADD_TO_STAT("MAX:MIN_VERSION", CountVer)
|
||||
global.ADD_TO_STAT("MAX:STOP_GET", CountStop)
|
||||
global.ADD_TO_STAT("MAX:AUTOCORRECT", CountAutoCorrectTime)
|
||||
global.ADD_TO_STAT("MAX:TIME_DELTA", DELTA_CURRENT_TIME)
|
||||
if (!Count)
|
||||
Count = 1
|
||||
if (!CountHot)
|
||||
CountHot = 1
|
||||
if (Count >= 20) {
|
||||
var SumDeltaAvg = 0;
|
||||
var AvgGlobTime = SumAvgDeltaTime / Count;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var Node = arr[i];
|
||||
if (!Node || Node.IsAddrList)
|
||||
continue;
|
||||
var Delta = AvgGlobTime - Node.DeltaGlobTime;
|
||||
SumDeltaAvg += Delta * Delta
|
||||
}
|
||||
SumDeltaAvg = Math.sqrt(SumDeltaAvg / Count)
|
||||
global.ADD_TO_STAT("MAX:DELTA_GLOB_TIME", 100 + AvgGlobTime)
|
||||
global.ADD_TO_STAT("MAX:DISP_DELTA_GLOB_TIME", SumDeltaAvg)
|
||||
arr.sort(function(a, b) {
|
||||
return a.DeltaGlobTime - b.DeltaGlobTime;
|
||||
})
|
||||
var SumDeltaAvgM = 0;
|
||||
var AvgGlobTimeM = arr[Math.trunc(arr.length / 2)].DeltaGlobTime;
|
||||
var Length = arr.length;
|
||||
var Start = Math.trunc(Length * 0.05);
|
||||
var End = Math.trunc(Length * 0.95);
|
||||
var NodesCount = 0;
|
||||
for (var i = Start; i < End; i++) {
|
||||
var Node = arr[i];
|
||||
if (!Node || Node.IsAddrList)
|
||||
continue;
|
||||
NodesCount++
|
||||
var Delta = AvgGlobTimeM - Node.DeltaGlobTime;
|
||||
SumDeltaAvgM += Delta * Delta
|
||||
}
|
||||
if (!NodesCount)
|
||||
NodesCount = 1
|
||||
SumDeltaAvgM = Math.sqrt(SumDeltaAvgM / NodesCount)
|
||||
global.ADD_TO_STAT("MAX:MEDIAN_GLOB_TIME", 100 + AvgGlobTimeM)
|
||||
global.ADD_TO_STAT("MAX:DISP_MEDIAN_GLOB_TIME", SumDeltaAvgM)
|
||||
}
|
||||
global.ADD_TO_STAT("MAX:DELTA_TIME_HOT", SumDeltaHot / CountHot)
|
||||
global.ADD_TO_STAT("MAX:DELTA_TIME_ACTUAL", SumDeltaActual / Count)
|
||||
global.ADD_TO_STAT("MAX:MEMORY_USAGE", process.memoryUsage().heapTotal / 1024 / 1024)
|
||||
global.ADD_TO_STAT("MAX:MEMORY_FREE", os.freemem() / 1024 / 1024)
|
||||
var SumUser = 0;
|
||||
var SumSys = 0;
|
||||
var SumIdle = 0;
|
||||
var cpus = os.cpus();
|
||||
for (var i = 0; i < cpus.length; i++) {
|
||||
var cpu = cpus[i];
|
||||
SumUser += cpu.times.user
|
||||
SumSys += cpu.times.sys + cpu.times.irq
|
||||
SumIdle += cpu.times.idle
|
||||
}
|
||||
if (GlSumUser !== undefined) {
|
||||
var maxsum = cpus.length * 1000;
|
||||
global.ADD_TO_STAT("MAX:CPU_USER_MODE", Math.min(maxsum, SumUser - GlSumUser))
|
||||
global.ADD_TO_STAT("MAX:CPU_SYS_MODE", Math.min(maxsum, SumSys - GlSumSys))
|
||||
global.ADD_TO_STAT("MAX:CPU_IDLE_MODE", Math.min(maxsum, SumIdle - GlSumIdle))
|
||||
global.ADD_TO_STAT("MAX:CPU", Math.min(maxsum, SumUser + SumSys - GlSumUser - GlSumSys))
|
||||
}
|
||||
GlSumUser = SumUser
|
||||
GlSumSys = SumSys
|
||||
GlSumIdle = SumIdle
|
||||
}
|
||||
GetNewMeta() {
|
||||
return crypto.randomBytes(32);
|
||||
}
|
||||
};
|
||||
class SMemBuffer {
|
||||
MetaMap1
|
||||
MetaMap2
|
||||
CheckName
|
||||
constructor(MaxTime, CheckName) {
|
||||
this.MetaMap1 = {}
|
||||
this.MetaMap2 = {}
|
||||
this.CheckName = CheckName
|
||||
setInterval(this.ShiftMapDirect.bind(this), MaxTime)
|
||||
}
|
||||
GetStrKey(Arr) {
|
||||
if (typeof Arr === "number" || typeof Arr === "string") {
|
||||
return Arr;
|
||||
} else {
|
||||
return GetHexFromAddres(Arr);
|
||||
}
|
||||
throw "NOT RET!";
|
||||
}
|
||||
LoadValue(Arr, bStay) {
|
||||
if (!Arr)
|
||||
return undefined;
|
||||
var Key = this.GetStrKey(Arr);
|
||||
var Value = this.MetaMap1[Key];
|
||||
if (Value !== undefined) {
|
||||
if (!bStay)
|
||||
delete this.MetaMap1[Key]
|
||||
return Value;
|
||||
}
|
||||
Value = this.MetaMap2[Key]
|
||||
if (Value !== undefined) {
|
||||
if (!bStay)
|
||||
delete this.MetaMap2[Key]
|
||||
}
|
||||
return Value;
|
||||
}
|
||||
SaveValue(Arr, Value) {
|
||||
var Key = this.GetStrKey(Arr);
|
||||
if (Value !== undefined)
|
||||
this.MetaMap1[Key] = Value
|
||||
}
|
||||
ShiftMapDirect() {
|
||||
if (glStopNode)
|
||||
return;
|
||||
if (this.CheckName) {
|
||||
var Count = 0;
|
||||
for (var key in this.MetaMap2) {
|
||||
Count++
|
||||
}
|
||||
if (Count) {
|
||||
global.ADD_TO_STAT(this.CheckName, 1, 1)
|
||||
}
|
||||
}
|
||||
this.MetaMap2 = this.MetaMap1
|
||||
this.MetaMap1 = {}
|
||||
}
|
||||
Clear() {
|
||||
this.MetaMap2 = {}
|
||||
this.MetaMap1 = {}
|
||||
}
|
||||
};
|
||||
class STreeBuffer {
|
||||
constructor(MaxTime, CompareFunction?, KeyType?, CheckName?) {
|
||||
this.KeyType = KeyType
|
||||
this.MetaTree1 = new RBTree(CompareFunction)
|
||||
this.MetaTree2 = new RBTree(CompareFunction)
|
||||
this.CheckName = CheckName
|
||||
setInterval(this.ShiftMapDirect.bind(this), MaxTime)
|
||||
}
|
||||
LoadValue(Hash, bStay) {
|
||||
if (!Hash)
|
||||
return undefined;
|
||||
if (typeof Hash !== this.KeyType)
|
||||
throw "MUST ONLY HASH ARRAY: " + Hash;
|
||||
var element = this.MetaTree1.find({ hash: Hash });
|
||||
if (element) {
|
||||
if (!bStay)
|
||||
this.MetaTree1.remove(element)
|
||||
return element.value;
|
||||
}
|
||||
element = this.MetaTree2.find({ hash: Hash })
|
||||
if (element) {
|
||||
if (!bStay)
|
||||
this.MetaTree2.remove(element)
|
||||
return element.value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
SaveValue(Hash, Value) {
|
||||
if (typeof Hash !== this.KeyType)
|
||||
throw "MUST ONLY TYPE=" + this.KeyType + " in " + Hash;
|
||||
if (Value !== undefined) {
|
||||
var element = this.MetaTree1.find({ hash: Hash });
|
||||
if (element)
|
||||
element.value = Value
|
||||
else
|
||||
this.MetaTree1.insert({ hash: Hash, value: Value })
|
||||
}
|
||||
}
|
||||
ShiftMapDirect() {
|
||||
if (this.CheckName && this.MetaTree2.size) {
|
||||
global.ADD_TO_STAT(this.CheckName, this.MetaTree2.size, 1)
|
||||
var it = this.MetaTree2.iterator(), Item;
|
||||
while ((Item = it.next()) !== null) {
|
||||
var Name = Item.value.Name;
|
||||
global.ADD_TO_STAT(this.CheckName + ":" + Name, 1, 1)
|
||||
}
|
||||
}
|
||||
this.MetaTree2.clear()
|
||||
var empty_tree = this.MetaTree2;
|
||||
this.MetaTree2 = this.MetaTree1
|
||||
this.MetaTree1 = empty_tree
|
||||
}
|
||||
Clear() {
|
||||
this.MetaTree1.clear()
|
||||
this.MetaTree2.clear()
|
||||
}
|
||||
};
|
||||
|
||||
function ReadHashFromBufDB(Map, BlockNum) {
|
||||
var MyHash = Map[BlockNum];
|
||||
if (!MyHash) {
|
||||
var Block = global.SERVER.ReadBlockHeaderDB(BlockNum);
|
||||
if (Block)
|
||||
MyHash = Block.Hash;
|
||||
else
|
||||
MyHash = [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];
|
||||
Map[BlockNum] = MyHash;
|
||||
}
|
||||
return MyHash;
|
||||
};
|
||||
|
||||
function GetCheckAccHash(Map, BlockNum, Hash) {
|
||||
var MyHash = Map[BlockNum];
|
||||
if (!MyHash) {
|
||||
MyHash = global.DApps.Accounts.GetHashOrUndefined(BlockNum);
|
||||
Map[BlockNum] = MyHash;
|
||||
}
|
||||
if (MyHash) {
|
||||
if (!Hash)
|
||||
return "=ERR:NO=";
|
||||
if (global.CompareArr(Hash, MyHash) !== 0)
|
||||
return "=ERR:BAD=";
|
||||
else
|
||||
return "=OK=";
|
||||
}
|
||||
else {
|
||||
if (!Hash)
|
||||
return "=OK=:NO";
|
||||
else
|
||||
return "=MY:NO=";
|
||||
}
|
||||
};
|
||||
global.GetCheckAccHash = GetCheckAccHash;
|
||||
global.ReadHashFromBufDB = ReadHashFromBufDB;
|
||||
global.STreeBuffer = STreeBuffer;
|
||||
global.TestCreateTr = TestCreateTr;
|
||||
|
||||
function TestCreateTr() {
|
||||
const FORMAT_CREATE = "{\
|
||||
Type:byte,\
|
||||
Currency:uint,\
|
||||
PubKey:arr33,\
|
||||
Description:str40,\
|
||||
Adviser:uint,\
|
||||
Reserve:arr7,\
|
||||
POWCreate:arr12,\
|
||||
}";
|
||||
var TR = {
|
||||
Type: 100, Currency: 0, PubKey: [2, 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], Description: "Description", Adviser: 10,
|
||||
};
|
||||
var Body = global.BufLib.GetBufferFromObject(TR, global.FORMAT_CREATE, 1000, {});
|
||||
var startTime = process.hrtime();
|
||||
var StartData = Date.now();
|
||||
var nonce = CreateHashBodyPOWInnerMinPower(Body, 1000, 17);
|
||||
var Time = process.hrtime(startTime);
|
||||
var power = GetPowPower(shaarr(Body));
|
||||
var deltaTime = (Time[0] * 1000 + Time[1] / 1e6) / 1000;
|
||||
var DeltaData = (new Date() - StartData) / 1000;
|
||||
global.ToLog("power=" + power + " nonce=" + nonce + " TIME=" + deltaTime + " sec" + " DeltaData=" + DeltaData + " sec");
|
||||
return { time1: deltaTime, time2: DeltaData };
|
||||
};
|
||||
|
||||
function CreateHashBody(body, Num, Nonce) {
|
||||
body.writeUIntLE(Num, body.length - 12, 6);
|
||||
body.writeUIntLE(Nonce, body.length - 6, 6);
|
||||
return global.shaarr(body);
|
||||
};
|
||||
|
||||
function CreateHashBodyPOWInnerMinPower(arr, BlockNum, MinPow) {
|
||||
var nonce = 0;
|
||||
while (1) {
|
||||
var arrhash = CreateHashBody(arr, BlockNum, nonce);
|
||||
var power = GetPowPower(arrhash);
|
||||
if (power >= MinPow) {
|
||||
return nonce;
|
||||
}
|
||||
nonce++;
|
||||
}
|
||||
};
|
||||
1376
src/core/block-exchange.ts
Normal file
1376
src/core/block-exchange.ts
Normal file
File diff suppressed because it is too large
Load Diff
16
src/core/block-loader-const.ts
Normal file
16
src/core/block-loader-const.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
global.PERIOD_GET_BLOCK = 300, global.COUNT_HISTORY_BLOCKS_FOR_LOAD = 600, global.COUNT_BLOCKS_FOR_CHECK_POW = 50, global.MAX_DELTA_COUNT_SUM_FOR_LOAD = 10,
|
||||
global.MAX_COUNT_CHAIN_LOAD = 120, global.PACKET_ALIVE_PERIOD = 4 * CONSENSUS_PERIOD_TIME, global.PACKET_ALIVE_PERIOD_NEXT_NODE = PACKET_ALIVE_PERIOD / 2,
|
||||
global.MAX_BLOCK_SEND = 8, global.COUNT_TASK_FOR_NODE = 10, global.FORMAT_BLOCK_TRANSFER = "{ BlockNum:uint, TreeHash:hash, arrContent:[tr], }",
|
||||
global.WRK_BLOCK_TRANSFER = {}, global.MAX_ACCOUNTS_TRANSFER = 1024, global.MAX_SMARTS_TRANSFER = 10, global.TEST_NETWORK && (global.MAX_ACCOUNTS_TRANSFER = 128,
|
||||
global.MAX_SMARTS_TRANSFER = 10), global.FORMAT_REST_TRANSFER = "{ Result:uint, Version:uint, Arr:[arr200], ProofHash:hash, ProofArrL:<hash>, ProofArrR:<hash>, }",
|
||||
global.FORMAT_SMART_TRANSFER = "{ Result:uint, Arr:[tr], }";
|
||||
1284
src/core/block-loader.ts
Normal file
1284
src/core/block-loader.ts
Normal file
File diff suppressed because it is too large
Load Diff
364
src/core/buffer.ts
Normal file
364
src/core/buffer.ts
Normal file
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
function Write(e,r,t,n,l)
|
||||
{
|
||||
if(!(e.len >= e.length))
|
||||
{
|
||||
if("number" == typeof t)
|
||||
throw ToLogTrace("ERRR StringFormat "), "ERR!!";
|
||||
var a = t;
|
||||
if("buffer" === a.substr(0, 6) && 6 < a.length)
|
||||
n = parseInt(a.substr(6)), a = "buffer";
|
||||
else
|
||||
if("arr" === a.substr(0, 3) && 3 < a.length)
|
||||
n = parseInt(a.substr(3)), a = "arr";
|
||||
else
|
||||
if("str" === a.substr(0, 3) && 3 < a.length)
|
||||
{
|
||||
var i = parseInt(a.substr(3));
|
||||
return r && e.write(r, e.len, i), void (e.len += i);
|
||||
}
|
||||
switch(a)
|
||||
{
|
||||
case "str":
|
||||
var f = toUTF8Array(r);
|
||||
65535 < (i = f.length) && (i = 0), e[e.len] = 255 & i, e[e.len + 1] = i >>> 8 & 255, e.len += 2;
|
||||
for(var s = 0; s < i; s++)
|
||||
e[e.len + s] = f[s];
|
||||
e.len += i;
|
||||
break;
|
||||
case "byte":
|
||||
r < 0 && (r = 0), e[e.len] = r, e.len += 1;
|
||||
break;
|
||||
case "double":
|
||||
e.writeDoubleLE(r, e.len, 8), e.len += 8;
|
||||
break;
|
||||
case "uint":
|
||||
r < 0 && (r = 0), 0xffffffffffff <= r && (r = 0), e.writeUIntLE(r, e.len, 6), e.len += 6;
|
||||
break;
|
||||
case "uint16":
|
||||
r < 0 && (r = 0), e[e.len] = 255 & r, e[e.len + 1] = r >>> 8 & 255, e.len += 2;
|
||||
break;
|
||||
case "uint32":
|
||||
r < 0 && (r = 0), e.writeUInt32LE(r, e.len, 4), e.len += 4;
|
||||
break;
|
||||
case "time":
|
||||
var u = r.valueOf();
|
||||
e.writeUIntLE(u, e.len, 6), e.len += 6;
|
||||
break;
|
||||
case "addres":
|
||||
case "hash":
|
||||
i = r ? Math.min(32, r.length) : 0;
|
||||
for(s = 0; s < i; s++)
|
||||
e[e.len + s] = r[s];
|
||||
e.len += 32;
|
||||
break;
|
||||
case "buffer":
|
||||
i = void 0 === n ? r.length : Math.min(n, r.length);
|
||||
for(s = 0; s < i; s++)
|
||||
e[e.len + s] = r[s];
|
||||
e.len += n;
|
||||
break;
|
||||
case "arr":
|
||||
i = r ? Math.min(n, r.length) : 0;
|
||||
for(s = 0; s < i; s++)
|
||||
e[e.len + s] = r[s];
|
||||
e.len += n;
|
||||
break;
|
||||
case "tr":
|
||||
i = r.length;
|
||||
MAX_TRANSACTION_SIZE > MAX_TRANSACTION_SIZE && (i = MAX_TRANSACTION_SIZE), e[e.len] = 255 & i, e[e.len + 1] = i >>> 8 & 255,
|
||||
e.len += 2;
|
||||
for(s = 0; s < i; s++)
|
||||
e[e.len + s] = r[s];
|
||||
e.len += i;
|
||||
break;
|
||||
case "data":
|
||||
i = r.length;
|
||||
e.writeUInt32LE(i, e.len, 4), e.len += 4;
|
||||
for(s = 0; s < i; s++)
|
||||
e[e.len + s] = r[s];
|
||||
e.len += i;
|
||||
break;
|
||||
case "hashSTR":
|
||||
var o = GetHexFromAddres(r);
|
||||
e.write(o, e.len, 64), e.len += 64;
|
||||
break;
|
||||
case "uintSTR":
|
||||
o = r.toString();
|
||||
e.write(o, e.len, 10), e.len += 10;
|
||||
break;
|
||||
default:
|
||||
l = l || {};
|
||||
var d = t.substr(0, 1);
|
||||
if("[" === d)
|
||||
{
|
||||
r && (i = r.length);
|
||||
var b = GetMiddleString(a);
|
||||
Write(e, i, "uint32");
|
||||
for(s = 0; s < i; s++)
|
||||
Write(e, r[s], b, void 0, l);
|
||||
}
|
||||
else
|
||||
if("<" === d)
|
||||
{
|
||||
r && (i = r.length);
|
||||
b = GetMiddleString(a);
|
||||
var h = 0, c = e.len;
|
||||
e.len += 4;
|
||||
for(s = 0; s < i; s++)
|
||||
r[s] && (h++, Write(e, s, "uint32"), Write(e, r[s], b, void 0, l));
|
||||
e.writeUInt32LE(h, c, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if("{" !== d)
|
||||
throw "Bad write type params: " + a;
|
||||
var g = l[a];
|
||||
g || (g = GetAttributes(GetMiddleString(a)), l[a] = g);
|
||||
for(s = 0; s < g.length; s++)
|
||||
{
|
||||
var v = g[s];
|
||||
Write(e, r[v.Key], v.Value, void 0, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function Read(e,r,t,n,l)
|
||||
{
|
||||
var a;
|
||||
if("number" == typeof r)
|
||||
throw ToLogTrace("ERR StringFormat"), "ERRR!";
|
||||
var i = r;
|
||||
if("buffer" === i.substr(0, 6))
|
||||
6 < i.length ? (t = parseInt(i.substr(6)), i = "buffer") : t = 0;
|
||||
else
|
||||
if("arr" === i.substr(0, 3))
|
||||
3 < i.length ? (t = parseInt(i.substr(3)), i = "arr") : t = 0;
|
||||
else
|
||||
if("str" === i.substr(0, 3))
|
||||
{
|
||||
if(3 < i.length)
|
||||
{
|
||||
var f = parseInt(i.substr(3));
|
||||
a = e.toString("utf8", e.len, e.len + f), e.len += f;
|
||||
for(var s = - 1, u = a.length - 1; 0 <= u; u--)
|
||||
if(0 !== a.charCodeAt(u))
|
||||
{
|
||||
s = u;
|
||||
break;
|
||||
}
|
||||
return a = 0 <= s ? a.substr(0, u + 1) : "";
|
||||
}
|
||||
t = 0;
|
||||
}
|
||||
switch(i)
|
||||
{
|
||||
case "str":
|
||||
f = e.len + 2 <= e.length ? e[e.len] + 256 * e[e.len + 1] : 0, e.len += 2;
|
||||
var o = e.slice(e.len, e.len + f);
|
||||
a = Utf8ArrayToStr(o), e.len += f;
|
||||
break;
|
||||
case "byte":
|
||||
a = e.len + 1 <= e.length ? e[e.len] : 0, e.len += 1;
|
||||
break;
|
||||
case "double":
|
||||
a = e.len + 8 <= e.length ? e.readDoubleLE(e.len, 8) : 0, e.len += 8;
|
||||
break;
|
||||
case "uint":
|
||||
a = e.len + 6 <= e.length ? e.readUIntLE(e.len, 6) : 0, e.len += 6;
|
||||
break;
|
||||
case "uint16":
|
||||
a = e.len + 2 <= e.length ? e[e.len] + 256 * e[e.len + 1] : 0, e.len += 2;
|
||||
break;
|
||||
case "uint32":
|
||||
a = e.len + 4 <= e.length ? e.readUInt32LE(e.len, 4) : 0, e.len += 4;
|
||||
break;
|
||||
case "time":
|
||||
if(l)
|
||||
throw "Bad read type params: time - DisableTime ON";
|
||||
a = e.len + 6 <= e.length ? e.readUIntLE(e.len, 6) : 0, a = new Date(a), e.len += 6;
|
||||
break;
|
||||
case "addres":
|
||||
case "hash":
|
||||
a = [];
|
||||
for(u = 0; u < 32; u++)
|
||||
e.len + u <= e.length ? a[u] = e[e.len + u] : a[u] = 0;
|
||||
e.len += 32;
|
||||
break;
|
||||
case "buffer":
|
||||
case "arr":
|
||||
a = e.len + t <= e.length ? e.slice(e.len, e.len + t) : Buffer.alloc(t), e.len += t;
|
||||
break;
|
||||
case "tr":
|
||||
if(e.len + 1 >= e.length)
|
||||
{
|
||||
a = void 0;
|
||||
break;
|
||||
}
|
||||
f = e[e.len] + 256 * e[e.len + 1];
|
||||
e.len += 2, a = e.slice(e.len, e.len + f), e.len += f;
|
||||
break;
|
||||
case "data":
|
||||
(f = e.len + 4 <= e.length ? e.readUInt32LE(e.len, 4) : 0) > e.length - e.len - 4 && (f = 0), e.len += 4, a = e.slice(e.len,
|
||||
e.len + f), e.len += f;
|
||||
break;
|
||||
case "hashSTR":
|
||||
var d = e.toString("utf8", e.len, e.len + 64);
|
||||
a = GetAddresFromHex(d), e.len += 64;
|
||||
break;
|
||||
case "uintSTR":
|
||||
d = e.toString("utf8", e.len, e.len + 10);
|
||||
a = parseInt(d), e.len += 10;
|
||||
break;
|
||||
default:
|
||||
n = n || {};
|
||||
var b = i.substr(0, 1);
|
||||
if("[" === b || "<" === b)
|
||||
{
|
||||
var h = "<" === b;
|
||||
a = [];
|
||||
var c = GetMiddleString(i);
|
||||
for(f = Read(e, "uint32"), u = 0; u < f && e.len <= e.length; u++)
|
||||
{
|
||||
h ? a[Read(e, "uint32")] = Read(e, c, void 0, n, l) : a[u] = Read(e, c, void 0, n, l);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if("{" !== b)
|
||||
throw "Bad read type params: " + i;
|
||||
var g = n[i];
|
||||
g || (g = GetAttributes(GetMiddleString(i)), n[i] = g), a = {};
|
||||
for(u = 0; u < g.length; u++)
|
||||
{
|
||||
var v = g[u];
|
||||
a[v.Key] = Read(e, v.Value, void 0, n, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
function BufWriteByte(e)
|
||||
{
|
||||
this[this.len] = e, this.len += 1;
|
||||
};
|
||||
|
||||
function BufWrite(e,r,t)
|
||||
{
|
||||
Write(this, e, r, t);
|
||||
};
|
||||
|
||||
function BufRead(e,r)
|
||||
{
|
||||
return Read(this, e, r);
|
||||
};
|
||||
|
||||
function GetNewBuffer(e)
|
||||
{
|
||||
var r = Buffer.alloc(e);
|
||||
return r.Read = BufRead.bind(r), r.Write = BufWrite.bind(r), r.len = 0, r;
|
||||
};
|
||||
|
||||
function GetReadBuffer(e)
|
||||
{
|
||||
var r = Buffer.from(e);
|
||||
return r.Read = BufRead.bind(r), r.Write = BufWrite.bind(r), r.len = 0, r;
|
||||
};
|
||||
|
||||
function GetObjectFromBuffer(e,r,t,n)
|
||||
{
|
||||
var l = Buffer.from(e);
|
||||
return l.len = 0, Read(l, r, void 0, t, n);
|
||||
};
|
||||
|
||||
function GetBufferFromObject(e,r,t,n,l)
|
||||
{
|
||||
var a = Buffer.alloc(t);
|
||||
return a.len = 0, Write(a, e, r, void 0, n), l || (a = a.slice(0, a.len)), a;
|
||||
};
|
||||
|
||||
function GetMiddleString(e)
|
||||
{
|
||||
return e.substr(1, e.length - 2);
|
||||
};
|
||||
|
||||
function GetMiddleString2(e,r,t)
|
||||
{
|
||||
for(var n = 0, l = "", a = 0; a < e.length; a++)
|
||||
{
|
||||
var i = e.substr(a, 1);
|
||||
if(" " !== i && "\n" !== i && (i !== r || 1 != ++n))
|
||||
{
|
||||
if(i === t && 0 === --n)
|
||||
break;
|
||||
n && (l += i);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
};
|
||||
|
||||
function GetAttributeStrings(e)
|
||||
{
|
||||
for(var r = 0, t = [], n = "", l = 0; l < e.length; l++)
|
||||
{
|
||||
var a = e.substr(l, 1);
|
||||
if("{" === a)
|
||||
r++;
|
||||
else
|
||||
if("}" === a)
|
||||
r--;
|
||||
else
|
||||
{
|
||||
if("," === a && 0 === r)
|
||||
{
|
||||
0 < n.length && t.push(n), n = "";
|
||||
continue;
|
||||
}
|
||||
if(" " === a || "\n" === a)
|
||||
continue;
|
||||
}
|
||||
n += a;
|
||||
}
|
||||
return 0 < n.length && t.push(n), t;
|
||||
};
|
||||
|
||||
function GetKeyValueStrings(e)
|
||||
{
|
||||
for(var r = "", t = 0; t < e.length; t++)
|
||||
{
|
||||
var n = e.substr(t, 1);
|
||||
if(" " !== n && "\n" !== n)
|
||||
{
|
||||
if(":" === n)
|
||||
return {Key:r, Value:e.substr(t + 1)};
|
||||
r += n;
|
||||
}
|
||||
}
|
||||
throw "Error format Key:Value = " + e;
|
||||
};
|
||||
|
||||
function GetAttributes(e)
|
||||
{
|
||||
for(var r = [], t = GetAttributeStrings(e), n = 0; n < t.length; n++)
|
||||
{
|
||||
var l = GetKeyValueStrings(t[n]);
|
||||
r.push(l);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
module.exports.GetNewBuffer = GetNewBuffer, module.exports.GetReadBuffer = GetReadBuffer, module.exports.alloc = GetNewBuffer,
|
||||
module.exports.from = GetReadBuffer, module.exports.Write = Write, module.exports.Read = Read, module.exports.GetObjectFromBuffer = GetObjectFromBuffer,
|
||||
module.exports.GetBufferFromObject = GetBufferFromObject;
|
||||
204
src/core/code.ts
Normal file
204
src/core/code.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* @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 * as fs from 'fs'
|
||||
const FORMAT_EVAL_SEND = "{MaxBlockNum:uint,Code:str,Sign:arr64}";
|
||||
module.exports = class CCode extends require("./base")
|
||||
{
|
||||
LastEvalCodeNum
|
||||
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
|
||||
super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
|
||||
if (!global.ADDRLIST_MODE && !this.VirtualMode) {
|
||||
setInterval(this.CheckLoadCodeTime.bind(this), 10 * 1000)
|
||||
}
|
||||
this.LastEvalCodeNum = 0
|
||||
global.CheckCreateDir(global.GetDataPath("Update"))
|
||||
}
|
||||
CheckLoadCodeTime() {
|
||||
if (global.START_LOAD_CODE.StartLoadNode && global.START_LOAD_CODE.StartLoadVersionNum) {
|
||||
var Delta = (new Date() as any) - global.START_LOAD_CODE.StartLoadVersionNumTime;
|
||||
if (Delta > 20 * 1000) {
|
||||
global.ToError("Cannot load code version:" + global.START_LOAD_CODE.StartLoadVersionNum + " from node: " + global.START_LOAD_CODE.StartLoadNode.ip + ":" + global.START_LOAD_CODE.StartLoadNode.port)
|
||||
this.ClearLoadCode()
|
||||
}
|
||||
}
|
||||
}
|
||||
ClearLoadCode() {
|
||||
global.START_LOAD_CODE.StartLoad = undefined
|
||||
global.START_LOAD_CODE.StartLoadVersionNum = 0
|
||||
global.START_LOAD_CODE.StartLoadVersionNumTime = 0
|
||||
}
|
||||
StartLoadCode(Node, CodeVersion) {
|
||||
var VersionNum = CodeVersion.VersionNum;
|
||||
global.START_LOAD_CODE.StartLoad = CodeVersion
|
||||
global.START_LOAD_CODE.StartLoadNode = Node
|
||||
global.START_LOAD_CODE.StartLoadVersionNum = VersionNum
|
||||
global.START_LOAD_CODE.StartLoadVersionNumTime = new Date()
|
||||
var fname = global.GetDataPath("Update/wallet-" + VersionNum + ".zip");
|
||||
if (fs.existsSync(fname)) {
|
||||
this.UseCode(VersionNum, false)
|
||||
return;
|
||||
}
|
||||
var Context = { "VersionNum": VersionNum };
|
||||
this.SendF(Node, { "Method": "GETCODE", "Context": Context, "Data": VersionNum })
|
||||
}
|
||||
static
|
||||
GETCODE_F() {
|
||||
return "uint";
|
||||
}
|
||||
RETCODE(Info) {
|
||||
var VersionNum = Info.Context.VersionNum;
|
||||
if (!VersionNum || !global.START_LOAD_CODE.StartLoad)
|
||||
return;
|
||||
var fname = global.GetDataPath("Update/wallet-" + VersionNum + ".zip");
|
||||
if (!fs.existsSync(fname)) {
|
||||
var Hash = global.shaarr(Info.Data);
|
||||
if (global.CompareArr(Hash, global.START_LOAD_CODE.StartLoad.Hash) === 0) {
|
||||
var file_handle = fs.openSync(fname, "w");
|
||||
fs.writeSync(file_handle, Info.Data, 0, Info.Data.length)
|
||||
fs.closeSync(file_handle)
|
||||
this.UseCode(VersionNum, global.USE_AUTO_UPDATE)
|
||||
}
|
||||
else {
|
||||
global.ToError("Error check hash of version code :" + global.START_LOAD_CODE.StartLoadVersionNum + " from node: " + Info.Node.ip + ":" + Info.Node.port)
|
||||
this.ClearLoadCode()
|
||||
this.AddCheckErrCount(Info.Node, 1, "Error check hash of version code")
|
||||
}
|
||||
}
|
||||
}
|
||||
UseCode(VersionNum, bUpdate) {
|
||||
if (bUpdate) {
|
||||
UpdateCodeFiles(VersionNum)
|
||||
}
|
||||
if (global.global.START_LOAD_CODE.StartLoad) {
|
||||
global.CODE_VERSION = global.START_LOAD_CODE.StartLoad
|
||||
this.ClearLoadCode()
|
||||
}
|
||||
}
|
||||
SetNewCodeVersion(Data, PrivateKey) {
|
||||
var fname = global.GetDataPath("ToUpdate/wallet.zip");
|
||||
if (fs.existsSync(fname)) {
|
||||
var fname2 = global.GetDataPath("Update/wallet-" + Data.VersionNum + ".zip");
|
||||
if (fs.existsSync(fname2)) {
|
||||
fs.unlinkSync(fname2)
|
||||
}
|
||||
var data = fs.readFileSync(fname);
|
||||
var Hash = global.shaarr(data);
|
||||
var file_handle = fs.openSync(fname2, "w");
|
||||
fs.writeSync(file_handle, data, 0, data.length)
|
||||
fs.closeSync(file_handle)
|
||||
var SignArr = arr2(Hash, GetArrFromValue(Data.VersionNum));
|
||||
var Sign = secp256k1.sign(SHA3BUF(SignArr), PrivateKey).signature;
|
||||
global.CODE_VERSION = Data
|
||||
global.CODE_VERSION.Hash = Hash
|
||||
global.CODE_VERSION.Sign = Sign
|
||||
return "OK Set new code version=" + Data.VersionNum;
|
||||
}
|
||||
else {
|
||||
return "File not exist: " + fname;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function UpdateCodeFiles(StartNum) {
|
||||
var fname = global.GetDataPath("Update");
|
||||
if (!fs.existsSync(fname))
|
||||
return 0;
|
||||
var arr = fs.readdirSync(fname);
|
||||
var arr2 = [];
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i].substr(0, 7) === "wallet-") {
|
||||
arr2.push(parseInt(arr[i].substr(7)));
|
||||
}
|
||||
}
|
||||
arr2.sort(function(a, b) {
|
||||
return a - b;
|
||||
});
|
||||
for (var i = 0; i < arr2.length; i++) {
|
||||
var Num = arr2[i];
|
||||
var Name = "wallet-" + Num + ".zip";
|
||||
var Path = fname + "/" + Name;
|
||||
global.ToLog("Check file:" + Name);
|
||||
if (fs.existsSync(Path)) {
|
||||
if (StartNum === Num) {
|
||||
global.ToLog("UnpackCodeFile:" + Name);
|
||||
UnpackCodeFile(Path);
|
||||
if (StartNum % 2 === 0) {
|
||||
global.RestartNode(1);
|
||||
}
|
||||
else {
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
global.ToLog("Delete old file update:" + Name);
|
||||
fs.unlinkSync(Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.UnpackCodeFile = UnpackCodeFile;
|
||||
|
||||
function UnpackCodeFile(fname) {
|
||||
var data = fs.readFileSync(fname);
|
||||
var reader = ZIP.Reader(data);
|
||||
reader.forEach(function(entry) {
|
||||
var Name = entry.getName();
|
||||
var Path = GetCodePath(Name);
|
||||
if (entry.isFile()) {
|
||||
var buf = entry.getData();
|
||||
global.CheckCreateDir(Path, true, true);
|
||||
var file_handle = fs.openSync(Path, "w");
|
||||
fs.writeSync(file_handle, buf, 0, buf.length);
|
||||
fs.closeSync(file_handle);
|
||||
}
|
||||
else {
|
||||
}
|
||||
});
|
||||
reader.close();
|
||||
};
|
||||
global.RestartNode = function RestartNode(bForce) {
|
||||
global.NeedRestart = 1;
|
||||
setTimeout(DoExit, 5000);
|
||||
if (global.nw || global.NWMODE) {
|
||||
} else {
|
||||
StopChildProcess();
|
||||
global.ToLog("********************************** FORCE RESTART!!!");
|
||||
return;
|
||||
}
|
||||
if (this.ActualNodes) {
|
||||
var it = this.ActualNodes.iterator(), Node;
|
||||
while ((Node = it.next()) !== null) {
|
||||
if (Node.Socket)
|
||||
CloseSocket(Node.Socket, "Restart");
|
||||
}
|
||||
}
|
||||
this.StopServer();
|
||||
this.StopNode();
|
||||
StopChildProcess();
|
||||
global.ToLog("****************************************** RESTART!!!");
|
||||
global.ToLog("EXIT 1");
|
||||
};
|
||||
|
||||
function DoExit() {
|
||||
global.ToLog("EXIT 2");
|
||||
if (global.nw || global.NWMODE) {
|
||||
global.ToLog("RESTART NW");
|
||||
var StrRun = '"' + process.argv[0] + '" .\n';
|
||||
StrRun += '"' + process.argv[0] + '" .\n';
|
||||
SaveToFile("run-next.bat", StrRun);
|
||||
const child_process = require('child_process');
|
||||
child_process.exec("run-next.bat", { shell: true });
|
||||
}
|
||||
global.ToLog("EXIT 3");
|
||||
process.exit(0);
|
||||
};
|
||||
1372
src/core/connect.ts
Normal file
1372
src/core/connect.ts
Normal file
File diff suppressed because it is too large
Load Diff
352
src/core/constant.ts
Normal file
352
src/core/constant.ts
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
global.UPDATE_CODE_VERSION_NUM = 1102;
|
||||
global.MIN_CODE_VERSION_NUM = 1094;
|
||||
global.MINING_VERSION_NUM = 0;
|
||||
global.InitParamsArg = InitParamsArg;
|
||||
global.CONST_NAME_ARR = [
|
||||
"AUTO_CORRECT_TIME",
|
||||
"DELTA_CURRENT_TIME",
|
||||
"COMMON_KEY",
|
||||
"NODES_NAME",
|
||||
"SERVER_PRIVATE_KEY_HEX",
|
||||
"USE_NET_FOR_SERVER_ADDRES",
|
||||
"NET_WORK_MODE",
|
||||
"STAT_MODE",
|
||||
"MAX_STAT_PERIOD",
|
||||
"LISTEN_IP",
|
||||
"HTTP_PORT_NUMBER",
|
||||
"HTTP_PORT_PASSWORD",
|
||||
"HTTP_IP_CONNECT",
|
||||
"WALLET_NAME",
|
||||
"WALLET_DESCRIPTION",
|
||||
"USE_HARD_API_V2",
|
||||
"COUNT_VIEW_ROWS",
|
||||
"USE_HINT",
|
||||
"ALL_VIEW_ROWS",
|
||||
"ALL_LOG_TO_CLIENT",
|
||||
"LOG_LEVEL",
|
||||
"USE_MINING",
|
||||
"MINING_START_TIME",
|
||||
"MINING_PERIOD_TIME",
|
||||
"POW_MAX_PERCENT",
|
||||
"COUNT_MINING_CPU",
|
||||
"SIZE_MINING_MEMORY",
|
||||
"POW_RUN_COUNT",
|
||||
"USE_AUTO_UPDATE",
|
||||
"RESTART_PERIOD_SEC",
|
||||
"MAX_GRAY_CONNECTIONS_TO_SERVER",
|
||||
"TRANSACTION_PROOF_COUNT",
|
||||
"UPDATE_NUM_COMPLETE",
|
||||
"LIMIT_SEND_TRAFIC",
|
||||
"WATCHDOG_DEV",
|
||||
"ADDRLIST_MODE",
|
||||
"CheckPointDelta",
|
||||
"MIN_VER_STAT",
|
||||
"DEBUG_WALLET",
|
||||
"HTTP_HOSTING_PORT",
|
||||
"HTTPS_HOSTING_DOMAIN",
|
||||
"HTTP_MAX_COUNT_ROWS",
|
||||
"HTTP_ADMIN_PASSORD",
|
||||
"WATCHDOG_BADACCOUNT",
|
||||
"RESYNC_CONDITION",
|
||||
"MAX_CONNECTIONS_COUNT",
|
||||
"TRUST_PROCESS_COUNT",
|
||||
"REST_START_COUNT",
|
||||
"LOAD_TO_BEGIN"
|
||||
];
|
||||
global.NODES_DELTA_CALC_HOUR = 4;
|
||||
global.USE_HARD_API_V2 = 0;
|
||||
global.USE_TICKET = 0;
|
||||
global.USE_CHECK_SENDING = 1;
|
||||
global.USE_LEVEL_WAY = 0;
|
||||
global.TR_TICKET_HASH_LENGTH = 10;
|
||||
global.BLOCKNUM_TICKET_ALGO = 16070000;
|
||||
global.WATCHDOG_BADACCOUNT = 1;
|
||||
global.WATCHDOG_DEV = 0;
|
||||
global.RESYNC_CONDITION = { "OWN_BLOCKS": 20, "K_POW": 5 };
|
||||
global.REST_BLOCK_SCALE = 1000;
|
||||
global.REST_START_COUNT = 10000;
|
||||
global.LOAD_TO_BEGIN = 2;
|
||||
global.DEBUG_WALLET = 0;
|
||||
global.CHECK_GLOBAL_TIME = 1;
|
||||
global.AUTO_CORRECT_TIME = 1;
|
||||
global.DELTA_CURRENT_TIME = 0;
|
||||
global.NODES_NAME = "";
|
||||
global.COMMON_KEY = "";
|
||||
global.SERVER_PRIVATE_KEY_HEX = undefined;
|
||||
global.USE_NET_FOR_SERVER_ADDRES = 1;
|
||||
global.NET_WORK_MODE = undefined;
|
||||
global.STAT_MODE = 0;
|
||||
global.MAX_STAT_PERIOD = 1 * 3600;
|
||||
global.UPDATE_NUM_COMPLETE = 0;
|
||||
global.WALLET_NAME = "TERA";
|
||||
global.WALLET_DESCRIPTION = "";
|
||||
global.USE_MINING = 0;
|
||||
global.POW_MAX_PERCENT = 50;
|
||||
global.POW_RUN_COUNT = 5000;
|
||||
global.POWRunPeriod = 1;
|
||||
global.CheckPointDelta = 20;
|
||||
global.ALL_LOG_TO_CLIENT = 1;
|
||||
global.LOG_LEVEL = 1;
|
||||
global.LIMIT_SEND_TRAFIC = 0;
|
||||
global.COUNT_VIEW_ROWS = 20;
|
||||
global.MIN_VER_STAT = 0;
|
||||
global.STOPGETBLOCK = 0;
|
||||
global.RESTART_PERIOD_SEC = 0;
|
||||
global.HARD_PACKET_PERIOD120 = 160;
|
||||
global.MINING_START_TIME = "";
|
||||
global.MINING_PERIOD_TIME = "";
|
||||
global.CHECK_RUN_MINING = 21 * 1000;
|
||||
global.CHECK_STOP_CHILD_PROCESS = 10 * 1000;
|
||||
global.COUNT_MINING_CPU = 0;
|
||||
global.SIZE_MINING_MEMORY = 0;
|
||||
global.HTTP_HOSTING_PORT = 0;
|
||||
global.HTTPS_HOSTING_DOMAIN = "";
|
||||
global.HTTP_MAX_COUNT_ROWS = 20;
|
||||
global.HTTP_ADMIN_PASSORD = "";
|
||||
require("./startlib.js");
|
||||
global.MIN_POWER_POW_HANDSHAKE = 12;
|
||||
global.USE_HINT = 0;
|
||||
global.ALL_VIEW_ROWS = 0;
|
||||
global.COUNT_BLOCK_PROOF = 300;
|
||||
global.COUNT_NODE_PROOF = 10;
|
||||
global.MIN_POWER_POW_MSG = 2;
|
||||
global.MEM_POOL_MSG_COUNT = 1000;
|
||||
global.MAX_LEVEL_SPECIALIZATION = 24;
|
||||
global.MIN_CONNECT_CHILD = 2;
|
||||
global.MAX_CONNECT_CHILD = 7;
|
||||
global.MAX_CONNECTIONS_COUNT = 1000;
|
||||
global.TRUST_PROCESS_COUNT = 80000;
|
||||
global.MAX_NODES_RETURN = 100;
|
||||
global.MAX_WAIT_PERIOD_FOR_STATUS = 10 * 1000;
|
||||
global.MAX_GRAY_CONNECTIONS_TO_SERVER = 10;
|
||||
global.MAX_PACKET_LENGTH = 450 * 1024;
|
||||
global.COUNT_BLOCKS_FOR_LOAD = 600;
|
||||
global.TR_LEN = 100;
|
||||
global.BLOCK_PROCESSING_LENGTH = 8;
|
||||
global.BLOCK_PROCESSING_LENGTH2 = global.BLOCK_PROCESSING_LENGTH * 2;
|
||||
global.CONSENSUS_PERIOD_TIME = 1000;
|
||||
global.MAX_BLOCK_SIZE = 130 * 1024;
|
||||
global.MAX_TRANSACTION_SIZE = 65535;
|
||||
global.MIN_TRANSACTION_SIZE = 32;
|
||||
global.MAX_TRANSACTION_COUNT = 2000;
|
||||
global.MAX_TRANSACTION_LIMIT = 250;
|
||||
global.MIN_POWER_POW_TR = 10;
|
||||
if (global.MIN_POWER_POW_BL === undefined)
|
||||
global.MIN_POWER_POW_BL = 5;
|
||||
global.GENERATE_BLOCK_ACCOUNT = 0;
|
||||
global.TOTAL_SUPPLY_TERA = 1e9;
|
||||
global.TRANSACTION_PROOF_COUNT = 1000 * 1000;
|
||||
global.MIN_POWER_POW_ACC_CREATE = 16;
|
||||
global.START_MINING = 2 * 1000 * 1000;
|
||||
global.REF_PERIOD_MINING = 1 * 1000 * 1000;
|
||||
global.DELTA_BLOCK_ACCOUNT_HASH = 1000;
|
||||
global.PERIOD_ACCOUNT_HASH = 50;
|
||||
global.START_BLOCK_ACCOUNT_HASH = 14500000;
|
||||
global.START_BLOCK_ACCOUNT_HASH3 = 24015000;
|
||||
global.NEW_ACCOUNT_INCREMENT = 22305000;
|
||||
global.NEW_BLOCK_REWARD1 = 22500000;
|
||||
global.NEW_FORMULA_START = 32000000;
|
||||
global.NEW_FORMULA_KTERA = 3;
|
||||
global.NEW_FORMULA_TARGET1 = 43000000;
|
||||
global.NEW_FORMULA_TARGET2 = 45000000;
|
||||
global.BLOCK_COUNT_IN_MEMORY = 40;
|
||||
global.HISTORY_BLOCK_COUNT = 40;
|
||||
global.MAX_SIZE_LOG = 200 * 1024 * 1024;
|
||||
global.READ_ONLY_DB = 0;
|
||||
global.USE_CHECK_SAVE_DB = 1;
|
||||
global.START_NETWORK_DATE = 1530446400000;
|
||||
global.NETWORK = "TERA-MAIN";
|
||||
global.DEF_MAJOR_VERSION = "0001";
|
||||
global.SMART_BLOCKNUM_START = 10000000;
|
||||
global.PRICE_DAO = function(BlockNum) {
|
||||
return { NewAccount: 10, NewSmart: 100, NewTokenSmart: 10000 };
|
||||
};
|
||||
if (global.LOCAL_RUN) {
|
||||
var Num = Date.now() - 300 * 1000;
|
||||
global.START_NETWORK_DATE = Math.trunc(Num / 1000) * 1000;
|
||||
}
|
||||
global.NEW_SIGN_TIME = 25500000;
|
||||
InitParamsArg();
|
||||
if (global.LOCAL_RUN) {
|
||||
global.REST_BLOCK_SCALE = 100;
|
||||
global.DELTA_BLOCK_ACCOUNT_HASH = 30;
|
||||
global.PERIOD_ACCOUNT_HASH = 10;
|
||||
global.START_BLOCK_ACCOUNT_HASH = 1;
|
||||
global.START_BLOCK_ACCOUNT_HASH3 = 1;
|
||||
global.BLOCKNUM_TICKET_ALGO = 1;
|
||||
global.SMART_BLOCKNUM_START = 0;
|
||||
global.START_MINING = 60;
|
||||
global.REF_PERIOD_MINING = 10;
|
||||
global.TEST_TRANSACTION_GENERATE = 0;
|
||||
global.MIN_POWER_POW_TR = 8;
|
||||
global.MIN_POWER_POW_ACC_CREATE = 8;
|
||||
global.NEW_ACCOUNT_INCREMENT = 1;
|
||||
global.NEW_BLOCK_REWARD1 = 1;
|
||||
global.NEW_FORMULA_START = 1;
|
||||
global.NEW_FORMULA_KTERA = 3;
|
||||
global.NEW_FORMULA_TARGET1 = 0;
|
||||
global.NEW_FORMULA_TARGET2 = 1;
|
||||
NETWORK = "LOCAL";
|
||||
global.ALL_VIEW_ROWS = 1;
|
||||
global.COUNT_NODE_PROOF = 1;
|
||||
global.NEW_SIGN_TIME = 0;
|
||||
}
|
||||
else
|
||||
if (global.TEST_NETWORK) {
|
||||
global.REST_BLOCK_SCALE = 100;
|
||||
var Num = Date.now() - 50 * 1000;
|
||||
console.log("CURRENT NUM: " + (Math.trunc(Num / 1000) * 1000));
|
||||
global.SMART_BLOCKNUM_START = 0;
|
||||
global.START_NETWORK_DATE = 1550843168000 + 1000 * 1000;
|
||||
global.START_MINING = 1000;
|
||||
global.REF_PERIOD_MINING = 1000;
|
||||
global.MIN_POWER_POW_ACC_CREATE = 8;
|
||||
global.TRANSACTION_PROOF_COUNT = 200 * 1000;
|
||||
global.MAX_SIZE_LOG = 20 * 1024 * 1024;
|
||||
global.START_BLOCK_ACCOUNT_HASH = 1000;
|
||||
global.START_BLOCK_ACCOUNT_HASH3 = 2356000;
|
||||
global.BLOCKNUM_TICKET_ALGO = 1;
|
||||
global.WALLET_NAME = "TEST";
|
||||
NETWORK = "TERA-TEST2";
|
||||
if (global.START_PORT_NUMBER === undefined)
|
||||
global.START_PORT_NUMBER = 40000;
|
||||
global.ALL_VIEW_ROWS = 1;
|
||||
global.NEW_ACCOUNT_INCREMENT = 1903000;
|
||||
global.NEW_BLOCK_REWARD1 = 1905000;
|
||||
global.NEW_FORMULA_START = 11402000;
|
||||
global.NEW_FORMULA_KTERA = 3;
|
||||
global.NEW_FORMULA_TARGET1 = 11403000;
|
||||
global.NEW_FORMULA_TARGET2 = 11405000;
|
||||
global.COUNT_NODE_PROOF = 8;
|
||||
global.REST_START_COUNT = 10000;
|
||||
global.NEW_SIGN_TIME = 4859000;
|
||||
}
|
||||
if (global.LOCAL_RUN) {
|
||||
global.BLOCKNUM_TICKET_ALGO = 0;
|
||||
global.MIN_POWER_POW_TR = 0;
|
||||
global.AUTO_CORRECT_TIME = 0;
|
||||
global.CHECK_GLOBAL_TIME = 0;
|
||||
}
|
||||
global.GetNetworkName = function() {
|
||||
return NETWORK + "-" + global.DEF_MAJOR_VERSION;
|
||||
};
|
||||
global.DEF_VERSION = global.DEF_MAJOR_VERSION + "." + global.UPDATE_CODE_VERSION_NUM;
|
||||
global.DEF_CLIENT = "TERA-CORE";
|
||||
global.FIRST_TIME_BLOCK = global.START_NETWORK_DATE;
|
||||
global.START_BLOCK_RUN = 0;
|
||||
if (global.START_IP === undefined)
|
||||
global.START_IP = "";
|
||||
if (global.LISTEN_IP === undefined)
|
||||
global.LISTEN_IP = "0.0.0.0";
|
||||
if (global.START_PORT_NUMBER === undefined)
|
||||
global.START_PORT_NUMBER = 30000;
|
||||
if (global.HTTP_PORT_PASSWORD === undefined)
|
||||
global.HTTP_PORT_PASSWORD = "";
|
||||
if (global.HTTP_IP_CONNECT === undefined)
|
||||
global.HTTP_IP_CONNECT = "";
|
||||
if (global.USE_AUTO_UPDATE === undefined)
|
||||
global.USE_AUTO_UPDATE = 1;
|
||||
if (global.USE_PARAM_JS === undefined)
|
||||
global.USE_PARAM_JS = 1;
|
||||
if (global.DATA_PATH === undefined)
|
||||
global.DATA_PATH = "";
|
||||
if (global.CREATE_ON_START === undefined)
|
||||
global.CREATE_ON_START = false;
|
||||
if (global.LOCAL_RUN === undefined)
|
||||
global.LOCAL_RUN = 0;
|
||||
if (global.CODE_PATH === undefined)
|
||||
global.CODE_PATH = process.cwd();
|
||||
if (global.DEBUG_MODE === undefined)
|
||||
global.DEBUG_MODE = 0;
|
||||
global.DEBUG_MODE = 0;
|
||||
if (typeof window === 'object') {
|
||||
window.RUN_CLIENT = 0;
|
||||
window.RUN_SERVER = 1;
|
||||
}
|
||||
global.RUN_CLIENT = 0;
|
||||
global.RUN_SERVER = 1;
|
||||
|
||||
function InitParamsArg() {
|
||||
for (var i = 1; i < process.argv.length; i++) {
|
||||
var str0 = process.argv[i];
|
||||
var str = str0.toUpperCase();
|
||||
if (str.substr(0, 9) == "HTTPPORT:") {
|
||||
global.HTTP_PORT_NUMBER = parseInt(str.substr(9));
|
||||
}
|
||||
else
|
||||
if (str.substr(0, 9) == "PASSWORD:") {
|
||||
global.HTTP_PORT_PASSWORD = str0.substr(9);
|
||||
}
|
||||
else
|
||||
if (str.substr(0, 5) == "PATH:")
|
||||
global.DATA_PATH = str0.substr(5);
|
||||
else
|
||||
if (str.substr(0, 5) == "PORT:")
|
||||
global.START_PORT_NUMBER = parseInt(str.substr(5));
|
||||
else
|
||||
if (str.substr(0, 3) == "IP:")
|
||||
global.START_IP = str.substr(3);
|
||||
else
|
||||
if (str.substr(0, 7) == "LISTEN:")
|
||||
global.LISTEN_IP = str.substr(7);
|
||||
else
|
||||
if (str.substr(0, 8) == "HOSTING:") {
|
||||
global.HTTP_HOSTING_PORT = parseInt(str.substr(8));
|
||||
}
|
||||
else
|
||||
if (str.substr(0, 13) == "STARTNETWORK:") {
|
||||
global.START_NETWORK_DATE = parseInt(str.substr(13));
|
||||
console.log("START_NETWORK_DATE: " + global.START_NETWORK_DATE);
|
||||
}
|
||||
else {
|
||||
switch (str) {
|
||||
case "CHILDPOW":
|
||||
global.CHILD_POW = true;
|
||||
break;
|
||||
case "ADDRLIST":
|
||||
global.ADDRLIST_MODE = true;
|
||||
break;
|
||||
case "CREATEONSTART":
|
||||
global.CREATE_ON_START = true;
|
||||
break;
|
||||
case "LOCALRUN":
|
||||
global.LOCAL_RUN = 1;
|
||||
break;
|
||||
case "TESTRUN":
|
||||
global.TEST_NETWORK = 1;
|
||||
break;
|
||||
case "NOLOCALRUN":
|
||||
global.LOCAL_RUN = 0;
|
||||
break;
|
||||
case "NOAUTOUPDATE":
|
||||
global.USE_AUTO_UPDATE = 0;
|
||||
break;
|
||||
case "NOPARAMJS":
|
||||
global.USE_PARAM_JS = 0;
|
||||
break;
|
||||
case "READONLYDB":
|
||||
global.READ_ONLY_DB = 1;
|
||||
break;
|
||||
case "NWMODE":
|
||||
global.NWMODE = 1;
|
||||
break;
|
||||
case "NOALIVE":
|
||||
global.NOALIVE = 1;
|
||||
break;
|
||||
case "DEV_MODE":
|
||||
global.DEV_MODE = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
993
src/core/crypto-library.ts
Normal file
993
src/core/crypto-library.ts
Normal file
@@ -0,0 +1,993 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
require("./library.js");
|
||||
import * as crypto from 'crypto'
|
||||
|
||||
let {
|
||||
sha3,
|
||||
secp256k1,
|
||||
SHA3BUF,
|
||||
GetSignHash,
|
||||
shaarr,
|
||||
ToLog
|
||||
} = global
|
||||
|
||||
global.MAX_SUPER_VALUE_POW = (1 << 30) * 2;
|
||||
var BuferForStr = Buffer.alloc(32);
|
||||
global.GetHexFromAddres = function(arr) {
|
||||
if (!arr)
|
||||
return "";
|
||||
if (arr.data !== undefined)
|
||||
arr = arr.data;
|
||||
for (var i = 0; i < 32; i++)
|
||||
BuferForStr[i] = arr[i];
|
||||
return BuferForStr.toString('hex').toUpperCase();
|
||||
};
|
||||
global.GetArr32FromHex = function(Str) {
|
||||
var array = new Uint8Array(32);
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
array[i] = parseInt(Str.substr(i * 2, 2), 16);
|
||||
}
|
||||
return array;
|
||||
};
|
||||
global.GetAddresFromHex = global.GetArr32FromHex;
|
||||
global.GetHexAddresFromPublicKey = function(arr) {
|
||||
return Buffer.from(arr.slice(1)).toString('hex').toUpperCase();
|
||||
};
|
||||
global.GetHexFromArr = function(arr) {
|
||||
if (!arr)
|
||||
return "";
|
||||
else
|
||||
return Buffer.from(arr).toString('hex').toUpperCase();
|
||||
};
|
||||
|
||||
function GetArrFromHex(Str) {
|
||||
var array = [];
|
||||
for (var i = 0; i < Str.length / 2; i++) {
|
||||
array[i] = parseInt(Str.substr(i * 2, 2), 16);
|
||||
}
|
||||
return array;
|
||||
};
|
||||
global.GetArrFromHex = GetArrFromHex;
|
||||
global.GetHexFromArrBlock = function(Arr, LenBlock) {
|
||||
var Str = "";
|
||||
var Arr2 = [];
|
||||
for (var i = 0; i < Arr.length; i++) {
|
||||
Arr2[i % LenBlock] = Arr[i];
|
||||
if (Arr2.length >= LenBlock) {
|
||||
Str += global.GetHexFromArr(Arr2) + "\n";
|
||||
Arr2 = [];
|
||||
}
|
||||
}
|
||||
if (Arr2.length) {
|
||||
Str += global.GetHexFromArr(Arr2);
|
||||
}
|
||||
return Str;
|
||||
};
|
||||
global.GetPublicKeyFromAddres = function(Arr) {
|
||||
var RetArr = new Uint8Array(33);
|
||||
RetArr[0] = 2;
|
||||
for (var i = 1; i < 33; i++)
|
||||
RetArr[i] = Arr[i - 1];
|
||||
return RetArr;
|
||||
};
|
||||
global.CheckDevelopSign = function(SignArr, Sign) {
|
||||
var hash = SHA3BUF(SignArr);
|
||||
for (var i = 0; i < DEVELOP_PUB_KEY_ARR.length; i++) {
|
||||
var Result = secp256k1.verify(hash, Buffer.from(Sign), DEVELOP_PUB_KEY_ARR[i]);
|
||||
if (Result)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
let GetPublicKeyFromAddres = global.GetPublicKeyFromAddres;
|
||||
global.CheckContextSecret = function(Context, ContextAddrTo) {
|
||||
if (ContextAddrTo.Secret === undefined) {
|
||||
if (ContextAddrTo.publickey === undefined) {
|
||||
ContextAddrTo.publickey = GetPublicKeyFromAddres(ContextAddrTo.addrArr);
|
||||
}
|
||||
ContextAddrTo.Secret = Context.KeyPair.computeSecret(ContextAddrTo.publickey, null);
|
||||
}
|
||||
};
|
||||
let CheckContextSecret = global.CheckContextSecret;
|
||||
global.GetSignHash = function(Context, ContextAddrTo, Msg) {
|
||||
CheckContextSecret(Context, ContextAddrTo);
|
||||
if (typeof Msg === "string")
|
||||
Msg = Buffer.from(Msg);
|
||||
var Buf = Buffer.concat([Msg, ContextAddrTo.Secret], Msg.length + ContextAddrTo.Secret.length);
|
||||
var Arr = global.shaarr(Buf);
|
||||
return Arr;
|
||||
};
|
||||
global.GetVerifyHash = function(Context, ContextAddr, Msg, Sign1) {
|
||||
try {
|
||||
var Sign2 = GetSignHash(Context, ContextAddr, Msg);
|
||||
for (var i = 0; i < Sign1.length; i++)
|
||||
if (Sign1[i] !== Sign2[i])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
global.GetKeyPair = function(password, secret, startnonce1, startnonce2) {
|
||||
secret = secret || "low";
|
||||
startnonce1 = startnonce1 || 0;
|
||||
startnonce2 = startnonce2 || 0;
|
||||
var KeyPair: any = crypto.createECDH('secp256k1');
|
||||
var private1 = global.shaarr(password);
|
||||
var private2 = private1;
|
||||
var nonce1 = 0;
|
||||
if (secret === "high")
|
||||
for (nonce1 = startnonce1; nonce1 < 2000000000; nonce1++) {
|
||||
private1[31] = nonce1 & 0xFF;
|
||||
private1[30] = (nonce1 >>> 8) & 0xFF;
|
||||
private1[29] = (nonce1 >>> 16) & 0xFF;
|
||||
private1[28] = (nonce1 >>> 24) & 0xFF;
|
||||
private2 = global.shaarr(private1);
|
||||
if (private2[0] === 0 && private2[1] === 0 && private2[2] === 0) {
|
||||
break;
|
||||
}
|
||||
nonce1++;
|
||||
}
|
||||
var nonce2;
|
||||
for (nonce2 = startnonce2; nonce2 < 2000000000; nonce2++) {
|
||||
private2[31] = nonce2 & 0xFF;
|
||||
private2[30] = (nonce2 >>> 8) & 0xFF;
|
||||
private2[29] = (nonce2 >>> 16) & 0xFF;
|
||||
private2[28] = (nonce2 >>> 24) & 0xFF;
|
||||
KeyPair.setPrivateKey(Buffer.from(private2));
|
||||
var Data = KeyPair.getPublicKey('', 'compressed');
|
||||
if (Data[0] === 2 && Data[31] === 0 && Data[32] === 0) {
|
||||
KeyPair.nonce1 = nonce1;
|
||||
KeyPair.nonce2 = nonce2;
|
||||
KeyPair.PubKeyArr = KeyPair.getPublicKey('', 'compressed');
|
||||
KeyPair.addrArr = KeyPair.PubKeyArr.slice(1);
|
||||
KeyPair.addrStr = global.GetHexFromArr(KeyPair.addrArr);
|
||||
KeyPair.addr = KeyPair.addrArr;
|
||||
return KeyPair;
|
||||
}
|
||||
nonce2++;
|
||||
}
|
||||
throw "ERROR. Key pair not found. Try another password!";
|
||||
};
|
||||
global.GetKeyPairTest = function(password, Power) {
|
||||
var KeyPair: any = crypto.createECDH('secp256k1');
|
||||
var private2 = global.shaarr(password);
|
||||
for (var nonce2 = 0; nonce2 < 1000000000; nonce2++) {
|
||||
private2[31] = nonce2 & 0xFF;
|
||||
private2[30] = (nonce2 >> 8) & 0xFF;
|
||||
private2[29] = (nonce2 >> 16) & 0xFF;
|
||||
private2[28] = (nonce2 >> 24) & 0xFF;
|
||||
KeyPair.setPrivateKey(Buffer.from(private2));
|
||||
var Data = KeyPair.getPublicKey('', 'compressed');
|
||||
if (Data[0] === 2) {
|
||||
if (Power) {
|
||||
var nBits = GetPowPower(Data.slice(1));
|
||||
if (nBits < Power)
|
||||
continue;
|
||||
}
|
||||
KeyPair.PubKeyArr = Data;
|
||||
KeyPair.addrArr = KeyPair.PubKeyArr.slice(1);
|
||||
KeyPair.addrStr = global.GetHexFromArr(KeyPair.addrArr);
|
||||
KeyPair.addr = KeyPair.addrArr;
|
||||
return KeyPair;
|
||||
}
|
||||
}
|
||||
throw "ERROR. Key pair not found. Try another password!";
|
||||
};
|
||||
|
||||
function GetArrFromValue(Num) {
|
||||
var arr = [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];
|
||||
arr[0] = Num & 0xFF;
|
||||
arr[1] = (Num >>> 8) & 0xFF;
|
||||
arr[2] = (Num >>> 16) & 0xFF;
|
||||
arr[3] = (Num >>> 24) & 0xFF;
|
||||
var NumH = Math.floor(Num / 4294967296);
|
||||
arr[4] = NumH & 0xFF;
|
||||
arr[5] = (NumH >>> 8) & 0xFF;
|
||||
return arr;
|
||||
};
|
||||
|
||||
function GetHashWithNonce(hash0, nonce) {
|
||||
return shaarr2(hash0, GetArrFromValue(nonce));
|
||||
};
|
||||
global.GetHashWithValues = GetHashWithValues;
|
||||
|
||||
function GetHashWithValues(hash0, value1, value2, bNotCopy) {
|
||||
var hash;
|
||||
if (bNotCopy)
|
||||
hash = hash0;
|
||||
else
|
||||
hash = hash0.slice();
|
||||
hash[0] = value1 & 0xFF;
|
||||
hash[1] = (value1 >>> 8) & 0xFF;
|
||||
hash[2] = (value1 >>> 16) & 0xFF;
|
||||
hash[3] = (value1 >>> 24) & 0xFF;
|
||||
hash[4] = value2 & 0xFF;
|
||||
hash[5] = (value2 >>> 8) & 0xFF;
|
||||
hash[6] = (value2 >>> 16) & 0xFF;
|
||||
hash[7] = (value2 >>> 24) & 0xFF;
|
||||
var arrhash = global.shaarr(hash);
|
||||
return arrhash;
|
||||
};
|
||||
|
||||
function GetPowPower(arrhash) {
|
||||
var SumBit = 0;
|
||||
if (arrhash)
|
||||
for (var i = 0; i < arrhash.length; i++) {
|
||||
var CurSum = Math.clz32(arrhash[i]) - 24;
|
||||
SumBit += CurSum;
|
||||
if (CurSum !== 8)
|
||||
break;
|
||||
}
|
||||
return SumBit;
|
||||
};
|
||||
|
||||
function GetPowValue(arrhash) {
|
||||
var value = (arrhash[0] << 23) * 2 + (arrhash[1] << 16) + (arrhash[2] << 8) + arrhash[3];
|
||||
value = value * 256 + arrhash[4];
|
||||
value = value * 256 + arrhash[5];
|
||||
return value;
|
||||
};
|
||||
global.CreateNoncePOWExtern = CreateNoncePOWExtern;
|
||||
|
||||
function CreateNoncePOWExtern(arr0, BlockNum, count, startnone) {
|
||||
var arr = [];
|
||||
for (var i = 0; i < arr0.length; i++)
|
||||
arr[i] = arr0[i];
|
||||
if (!startnone)
|
||||
startnone = 0;
|
||||
var maxnonce = 0;
|
||||
var supervalue = MAX_SUPER_VALUE_POW;
|
||||
for (var nonce = startnone; nonce <= startnone + count; nonce++) {
|
||||
var arrhash = GetHashWithValues(arr, nonce, BlockNum, true);
|
||||
var value = GetPowValue(arrhash);
|
||||
if (value < supervalue) {
|
||||
maxnonce = nonce;
|
||||
supervalue = value;
|
||||
}
|
||||
}
|
||||
return maxnonce;
|
||||
};
|
||||
global.CreateNoncePOWExternMinPower = CreateNoncePOWExternMinPower;
|
||||
|
||||
function CreateNoncePOWExternMinPower(arr0, BlockNum, MinPow) {
|
||||
var arr = [];
|
||||
for (var i = 0; i < arr0.length; i++)
|
||||
arr[i] = arr0[i];
|
||||
var nonce = 0;
|
||||
while (1) {
|
||||
var arrhash = GetHashWithValues(arr, nonce, BlockNum, true);
|
||||
var power = GetPowPower(arrhash);
|
||||
if (power >= MinPow) {
|
||||
return nonce;
|
||||
}
|
||||
nonce++;
|
||||
}
|
||||
};
|
||||
global.CreateNoncePOWInner = function(arr0, count) {
|
||||
var Hash;
|
||||
var arr = arr0.slice();
|
||||
var maxnonce = 0;
|
||||
var supervalue = MAX_SUPER_VALUE_POW;
|
||||
for (var nonce = 0; nonce < count; nonce++) {
|
||||
var hashTest = GetHashWithNonce(arr, nonce);
|
||||
var value = GetPowValue(hashTest);
|
||||
if (value < supervalue) {
|
||||
maxnonce = nonce;
|
||||
supervalue = value;
|
||||
Hash = hashTest;
|
||||
}
|
||||
}
|
||||
return { nonce: maxnonce, Hash: Hash };
|
||||
};
|
||||
global.CreateAddrPOW = function(SeqHash, AddrArr, MaxHash, Start, CountNonce, BlockNum) {
|
||||
var MaxNonce = 0;
|
||||
var bFind = 0;
|
||||
for (var nonce = Start; nonce < Start + CountNonce; nonce++) {
|
||||
AddrArr[6] = nonce & 0xFF;
|
||||
AddrArr[7] = (nonce >>> 8) & 0xFF;
|
||||
AddrArr[8] = (nonce >>> 16) & 0xFF;
|
||||
AddrArr[9] = (nonce >>> 24) & 0xFF;
|
||||
var HashTest = shaarrblock2(SeqHash, AddrArr, BlockNum);
|
||||
if (global.CompareArr(MaxHash, HashTest) >= 0) {
|
||||
MaxHash = HashTest;
|
||||
MaxNonce = nonce;
|
||||
bFind = 1;
|
||||
}
|
||||
}
|
||||
if (bFind) {
|
||||
AddrArr[6] = MaxNonce & 0xFF;
|
||||
AddrArr[7] = (MaxNonce >>> 8) & 0xFF;
|
||||
AddrArr[8] = (MaxNonce >>> 16) & 0xFF;
|
||||
AddrArr[9] = (MaxNonce >>> 24) & 0xFF;
|
||||
}
|
||||
return { MaxHash: MaxHash, LastNonce: nonce, MaxNonce: MaxNonce, bFind: bFind };
|
||||
};
|
||||
|
||||
function IsZeroArr(arr) {
|
||||
if (arr)
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
if (arr[i])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
function CalcHashFromArray(ArrHashes, bOriginalSeq) {
|
||||
if (bOriginalSeq === undefined)
|
||||
ArrHashes.sort(CompareArr);
|
||||
var Buf = [];
|
||||
for (var i = 0; i < ArrHashes.length; i++) {
|
||||
var Value = ArrHashes[i];
|
||||
for (var n = 0; n < Value.length; n++)
|
||||
Buf.push(Value[n]);
|
||||
}
|
||||
if (Buf.length === 0)
|
||||
return [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];
|
||||
else
|
||||
if (Buf.length === 32)
|
||||
return Buf;
|
||||
var Hash = global.shaarr(Buf);
|
||||
return Hash;
|
||||
};
|
||||
|
||||
function CalcHash3FromArray(ArrHashes, bOriginalSeq) {
|
||||
if (bOriginalSeq === undefined)
|
||||
ArrHashes.sort(CompareArr);
|
||||
var Buf = [];
|
||||
for (var i = 0; i < ArrHashes.length; i++) {
|
||||
var Value = ArrHashes[i];
|
||||
for (var n = 0; n < Value.length; n++)
|
||||
Buf.push(Value[n]);
|
||||
}
|
||||
if (Buf.length === 0)
|
||||
return [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];
|
||||
else
|
||||
if (Buf.length === 32)
|
||||
return Buf;
|
||||
var Hash = global.sha3(Buf);
|
||||
return Hash;
|
||||
};
|
||||
|
||||
function CalcMerkl3FromArray(Arr, Tree0?) {
|
||||
var Tree, bSort;
|
||||
if (Tree0) {
|
||||
bSort = 0;
|
||||
Tree = Tree0;
|
||||
}
|
||||
else {
|
||||
bSort = 1;
|
||||
Tree = { Levels: [], Full: true };
|
||||
}
|
||||
Tree.Levels.push(Arr);
|
||||
if (Arr.length < 2) {
|
||||
if (Arr.length === 0)
|
||||
Tree.Root = [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];
|
||||
else {
|
||||
if (Arr[0].length === 32)
|
||||
Tree.Root = Arr[0];
|
||||
else
|
||||
Tree.Root = global.sha3(Arr[0]);
|
||||
}
|
||||
return Tree;
|
||||
}
|
||||
if (bSort) {
|
||||
Arr.sort(CompareArr);
|
||||
}
|
||||
var Arr2 = [];
|
||||
var len = Math.floor(Arr.length / 2);
|
||||
for (var i = 0; i < len; i++) {
|
||||
var Hash = sha3arr2(Arr[i * 2], Arr[i * 2 + 1]);
|
||||
Arr2.push(Hash);
|
||||
}
|
||||
if (len * 2 !== Arr.length) {
|
||||
Arr2.push(Arr[Arr.length - 1]);
|
||||
}
|
||||
return CalcMerkl3FromArray(Arr2, Tree);
|
||||
};
|
||||
|
||||
function CalcMerkl0FromArray(Arr, Tree0?) {
|
||||
var Tree, bSort;
|
||||
if (Tree0) {
|
||||
bSort = 0;
|
||||
Tree = Tree0;
|
||||
}
|
||||
else {
|
||||
bSort = 1;
|
||||
Tree = { Levels: [], Full: true };
|
||||
}
|
||||
Tree.Levels.push(Arr);
|
||||
if (Arr.length < 2) {
|
||||
if (Arr.length === 0)
|
||||
Tree.Root = [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];
|
||||
else {
|
||||
if (Arr[0].length === 32)
|
||||
Tree.Root = Arr[0];
|
||||
else
|
||||
Tree.Root = global.shaarr(Arr[0]);
|
||||
}
|
||||
return Tree;
|
||||
}
|
||||
if (bSort) {
|
||||
Arr.sort(CompareArr);
|
||||
}
|
||||
var Arr2 = [];
|
||||
var len = Math.floor(Arr.length / 2);
|
||||
for (var i = 0; i < len; i++) {
|
||||
var Hash = shaarr2(Arr[i * 2], Arr[i * 2 + 1]);
|
||||
Arr2.push(Hash);
|
||||
}
|
||||
if (len * 2 !== Arr.length) {
|
||||
Arr2.push(Arr[Arr.length - 1]);
|
||||
}
|
||||
return CalcMerkl0FromArray(Arr2, Tree);
|
||||
};
|
||||
|
||||
function CalcMerklFromArray(BlockNum, Arr) {
|
||||
if (BlockNum >= global.BLOCKNUM_TICKET_ALGO) {
|
||||
return CalcMerkl3FromArray(Arr);
|
||||
}
|
||||
else {
|
||||
return CalcMerkl0FromArray(Arr);
|
||||
}
|
||||
};
|
||||
|
||||
function CalcTreeHashFromArrBody(BlockNum, arrContent) {
|
||||
if (arrContent) {
|
||||
var arrHASH = [];
|
||||
for (var i = 0; i < arrContent.length; i++) {
|
||||
var HASH;
|
||||
if (BlockNum >= global.BLOCKNUM_TICKET_ALGO)
|
||||
HASH = global.sha3(arrContent[i]);
|
||||
else
|
||||
HASH = global.shaarr(arrContent[i]);
|
||||
arrHASH.push(HASH);
|
||||
}
|
||||
var Tree = CalcMerklFromArray(BlockNum, arrHASH);
|
||||
return Tree.Root;
|
||||
}
|
||||
else {
|
||||
return [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];
|
||||
}
|
||||
};
|
||||
|
||||
function TestMerklTree() {
|
||||
var h1 = [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 h2 = global.sha3("2");
|
||||
var h3 = global.sha3("3");
|
||||
var h4 = global.sha3("4");
|
||||
var h5 = global.sha3("5");
|
||||
var Tree: any = { RecalcCount: 0 };
|
||||
var CalcMap = {};
|
||||
Tree.LevelsHash = [[h1, h2]];
|
||||
Tree.RecalcCount = 0;
|
||||
CalcMap[0] = 1;
|
||||
CalcMap[1] = 1;
|
||||
UpdateMerklTree(Tree, CalcMap, 0);
|
||||
CalcMap = {};
|
||||
Tree.LevelsHash[0] = [h1, h2, h3, h4];
|
||||
Tree.RecalcCount = 0;
|
||||
CalcMap[2] = 1;
|
||||
CalcMap[3] = 1;
|
||||
UpdateMerklTree(Tree, CalcMap, 0);
|
||||
CalcMap = {};
|
||||
Tree.LevelsHash[0] = [h1, h2, h3];
|
||||
Tree.RecalcCount = 0;
|
||||
CalcMap[Tree.LevelsHash[0].length - 1] = 1;
|
||||
UpdateMerklTree(Tree, CalcMap, 0);
|
||||
global.ToLog("Root=" + global.GetHexFromArr(Tree.Root));
|
||||
global.ToLog("RecalcCount=" + Tree.RecalcCount);
|
||||
return Tree;
|
||||
};
|
||||
if (0)
|
||||
setTimeout(function() {
|
||||
TestMerkleProof(100);
|
||||
global.ToLog("=========END=========");
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
function TestMerkleProof(CountTest) {
|
||||
for (var R = 0; R < CountTest; R++) {
|
||||
var CountItems = Math.floor(Math.random() * CountTest);
|
||||
var Tree: any = { RecalcCount: 0 };
|
||||
var CalcMap = {};
|
||||
Tree.LevelsHash = [];
|
||||
Tree.LevelsHash[0] = [];
|
||||
for (var i = 0; i < CountItems; i++) {
|
||||
CalcMap[i] = 1;
|
||||
Tree.LevelsHash[0][i] = global.sha3("" + i + "-" + R);
|
||||
}
|
||||
UpdateMerklTree(Tree, CalcMap, 0);
|
||||
global.ToLog("Hash1=" + global.GetHexFromArr(Tree.Root) + " CountItems:" + CountItems);
|
||||
var FirstNum = Math.floor(Math.random() * CountItems / 2);
|
||||
var LastNum = Math.floor(CountItems / 2 + Math.random() * CountItems / 2);
|
||||
var Ret = GetMerkleProof(Tree.LevelsHash, FirstNum, LastNum);
|
||||
var ArrM = Tree.LevelsHash[0].slice(FirstNum, LastNum + 1);
|
||||
var Hash2 = CheckMerkleProof(Ret.ArrL, ArrM, Ret.ArrR);
|
||||
global.ToLog("Hash2=" + global.GetHexFromArr(Hash2) + " FirstNum=" + FirstNum + "/" + LastNum);
|
||||
if (global.CompareArr(Tree.Root, Hash2) !== 0)
|
||||
throw ("=========ERROR HASHTEST==============");
|
||||
else
|
||||
global.ToLog("=========OK==============");
|
||||
}
|
||||
};
|
||||
|
||||
function GetMerkleProof(LevelsHash, FirstNum, LastNum) {
|
||||
var ArrL = [];
|
||||
var ArrR = [];
|
||||
var CurL = FirstNum;
|
||||
var CurR = LastNum;
|
||||
for (var L = 0; L < LevelsHash.length; L++) {
|
||||
var LevelArr = LevelsHash[L];
|
||||
if (CurL % 2 === 1)
|
||||
ArrL[L] = LevelArr[CurL - 1];
|
||||
if (CurR % 2 === 0 && CurR + 1 < LevelArr.length)
|
||||
ArrR[L] = LevelArr[CurR + 1];
|
||||
CurL = Math.floor(CurL / 2);
|
||||
CurR = Math.floor(CurR / 2);
|
||||
}
|
||||
return { ArrL: ArrL, ArrR: ArrR };
|
||||
};
|
||||
|
||||
function CheckMerkleProof(ArrL, ArrM, ArrR) {
|
||||
var L = 0;
|
||||
var Arr2 = ArrM;
|
||||
while (true) {
|
||||
var Arr = [].concat(Arr2);
|
||||
if (ArrL[L])
|
||||
Arr.unshift(ArrL[L]);
|
||||
if (ArrR[L])
|
||||
Arr.push(ArrR[L]);
|
||||
if (Arr.length <= 1 && L >= ArrL.length && L >= ArrR.length) {
|
||||
if (!Arr.length)
|
||||
return [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];
|
||||
return Arr[0];
|
||||
}
|
||||
var length2 = Math.floor(Arr.length / 2);
|
||||
Arr2 = [];
|
||||
for (i = 0; i < length2; i++) {
|
||||
var Hash = global.sha3(arr2(Arr[i * 2], Arr[i * 2 + 1]));
|
||||
Arr2.push(Hash);
|
||||
}
|
||||
if (Arr.length / 2 > length2)
|
||||
Arr2.push(Arr[Arr.length - 1]);
|
||||
L++;
|
||||
}
|
||||
};
|
||||
|
||||
function UpdateMerklTree(Tree, CalcMap: any, NumLevel) {
|
||||
var HashArr = Tree.LevelsHash[NumLevel];
|
||||
if (!HashArr || !HashArr.length) {
|
||||
Tree.LevelsHash.length = NumLevel + 1;
|
||||
Tree.MaxLevel = NumLevel;
|
||||
Tree.Root = [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];
|
||||
}
|
||||
else
|
||||
if (HashArr.length === 1) {
|
||||
Tree.LevelsHash.length = NumLevel + 1;
|
||||
Tree.MaxLevel = NumLevel;
|
||||
Tree.Root = HashArr[0];
|
||||
}
|
||||
else {
|
||||
var CalcMap2 = {};
|
||||
var HashArr2 = Tree.LevelsHash[NumLevel + 1];
|
||||
if (!HashArr2) {
|
||||
HashArr2 = [];
|
||||
Tree.LevelsHash[NumLevel + 1] = HashArr2;
|
||||
}
|
||||
var len2 = Math.floor(HashArr.length / 2);
|
||||
HashArr2.length = Math.floor(0.5 + HashArr.length / 2);
|
||||
var Count = 0;
|
||||
var LastIndex = HashArr.length - 1;
|
||||
for (var key in CalcMap) {
|
||||
var i2 = Math.floor(key as any / 2);
|
||||
if (i2 < len2) {
|
||||
Count++;
|
||||
CalcMap2[i2] = 1;
|
||||
HashArr2[i2] = global.sha3(arr2(HashArr[i2 * 2], HashArr[i2 * 2 + 1]));
|
||||
}
|
||||
else {
|
||||
if (key as any > LastIndex) {
|
||||
CalcMap2[i2] = 1;
|
||||
}
|
||||
else
|
||||
if (i2 === len2) {
|
||||
Count++;
|
||||
CalcMap2[i2] = 1;
|
||||
HashArr2[i2] = HashArr[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Count) {
|
||||
Tree.RecalcCount += Count;
|
||||
UpdateMerklTree(Tree, CalcMap2, NumLevel + 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649, 0, 2147516545, 2147483648, 32777,
|
||||
2147483648, 138, 0, 136, 0, 2147516425, 0, 2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771, 2147483648,
|
||||
32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648, 2147516545, 2147483648, 32896, 2147483648, 2147483649,
|
||||
0, 2147516424, 2147483648];
|
||||
|
||||
function Mesh(s, Count) {
|
||||
var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15,
|
||||
b16, b17, b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33, b34, b35, b36, b37, b38, b39, b40,
|
||||
b41, b42, b43, b44, b45, b46, b47, b48, b49;
|
||||
for (n = 0; n < Count; n += 2) {
|
||||
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
|
||||
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
|
||||
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
|
||||
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
|
||||
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
|
||||
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
|
||||
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
|
||||
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
|
||||
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
|
||||
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
|
||||
h = c8 ^ ((c2 << 1) | (c3 >>> 31));
|
||||
l = c9 ^ ((c3 << 1) | (c2 >>> 31));
|
||||
s[0] ^= h;
|
||||
s[1] ^= l;
|
||||
s[10] ^= h;
|
||||
s[11] ^= l;
|
||||
s[20] ^= h;
|
||||
s[21] ^= l;
|
||||
s[30] ^= h;
|
||||
s[31] ^= l;
|
||||
s[40] ^= h;
|
||||
s[41] ^= l;
|
||||
h = c0 ^ ((c4 << 1) | (c5 >>> 31));
|
||||
l = c1 ^ ((c5 << 1) | (c4 >>> 31));
|
||||
s[2] ^= h;
|
||||
s[3] ^= l;
|
||||
s[12] ^= h;
|
||||
s[13] ^= l;
|
||||
s[22] ^= h;
|
||||
s[23] ^= l;
|
||||
s[32] ^= h;
|
||||
s[33] ^= l;
|
||||
s[42] ^= h;
|
||||
s[43] ^= l;
|
||||
h = c2 ^ ((c6 << 1) | (c7 >>> 31));
|
||||
l = c3 ^ ((c7 << 1) | (c6 >>> 31));
|
||||
s[4] ^= h;
|
||||
s[5] ^= l;
|
||||
s[14] ^= h;
|
||||
s[15] ^= l;
|
||||
s[24] ^= h;
|
||||
s[25] ^= l;
|
||||
s[34] ^= h;
|
||||
s[35] ^= l;
|
||||
s[44] ^= h;
|
||||
s[45] ^= l;
|
||||
h = c4 ^ ((c8 << 1) | (c9 >>> 31));
|
||||
l = c5 ^ ((c9 << 1) | (c8 >>> 31));
|
||||
s[6] ^= h;
|
||||
s[7] ^= l;
|
||||
s[16] ^= h;
|
||||
s[17] ^= l;
|
||||
s[26] ^= h;
|
||||
s[27] ^= l;
|
||||
s[36] ^= h;
|
||||
s[37] ^= l;
|
||||
s[46] ^= h;
|
||||
s[47] ^= l;
|
||||
h = c6 ^ ((c0 << 1) | (c1 >>> 31));
|
||||
l = c7 ^ ((c1 << 1) | (c0 >>> 31));
|
||||
s[8] ^= h;
|
||||
s[9] ^= l;
|
||||
s[18] ^= h;
|
||||
s[19] ^= l;
|
||||
s[28] ^= h;
|
||||
s[29] ^= l;
|
||||
s[38] ^= h;
|
||||
s[39] ^= l;
|
||||
s[48] ^= h;
|
||||
s[49] ^= l;
|
||||
b0 = s[0];
|
||||
b1 = s[1];
|
||||
b32 = (s[11] << 4) | (s[10] >>> 28);
|
||||
b33 = (s[10] << 4) | (s[11] >>> 28);
|
||||
b14 = (s[20] << 3) | (s[21] >>> 29);
|
||||
b15 = (s[21] << 3) | (s[20] >>> 29);
|
||||
b46 = (s[31] << 9) | (s[30] >>> 23);
|
||||
b47 = (s[30] << 9) | (s[31] >>> 23);
|
||||
b28 = (s[40] << 18) | (s[41] >>> 14);
|
||||
b29 = (s[41] << 18) | (s[40] >>> 14);
|
||||
b20 = (s[2] << 1) | (s[3] >>> 31);
|
||||
b21 = (s[3] << 1) | (s[2] >>> 31);
|
||||
b2 = (s[13] << 12) | (s[12] >>> 20);
|
||||
b3 = (s[12] << 12) | (s[13] >>> 20);
|
||||
b34 = (s[22] << 10) | (s[23] >>> 22);
|
||||
b35 = (s[23] << 10) | (s[22] >>> 22);
|
||||
b16 = (s[33] << 13) | (s[32] >>> 19);
|
||||
b17 = (s[32] << 13) | (s[33] >>> 19);
|
||||
b48 = (s[42] << 2) | (s[43] >>> 30);
|
||||
b49 = (s[43] << 2) | (s[42] >>> 30);
|
||||
b40 = (s[5] << 30) | (s[4] >>> 2);
|
||||
b41 = (s[4] << 30) | (s[5] >>> 2);
|
||||
b22 = (s[14] << 6) | (s[15] >>> 26);
|
||||
b23 = (s[15] << 6) | (s[14] >>> 26);
|
||||
b4 = (s[25] << 11) | (s[24] >>> 21);
|
||||
b5 = (s[24] << 11) | (s[25] >>> 21);
|
||||
b36 = (s[34] << 15) | (s[35] >>> 17);
|
||||
b37 = (s[35] << 15) | (s[34] >>> 17);
|
||||
b18 = (s[45] << 29) | (s[44] >>> 3);
|
||||
b19 = (s[44] << 29) | (s[45] >>> 3);
|
||||
b10 = (s[6] << 28) | (s[7] >>> 4);
|
||||
b11 = (s[7] << 28) | (s[6] >>> 4);
|
||||
b42 = (s[17] << 23) | (s[16] >>> 9);
|
||||
b43 = (s[16] << 23) | (s[17] >>> 9);
|
||||
b24 = (s[26] << 25) | (s[27] >>> 7);
|
||||
b25 = (s[27] << 25) | (s[26] >>> 7);
|
||||
b6 = (s[36] << 21) | (s[37] >>> 11);
|
||||
b7 = (s[37] << 21) | (s[36] >>> 11);
|
||||
b38 = (s[47] << 24) | (s[46] >>> 8);
|
||||
b39 = (s[46] << 24) | (s[47] >>> 8);
|
||||
b30 = (s[8] << 27) | (s[9] >>> 5);
|
||||
b31 = (s[9] << 27) | (s[8] >>> 5);
|
||||
b12 = (s[18] << 20) | (s[19] >>> 12);
|
||||
b13 = (s[19] << 20) | (s[18] >>> 12);
|
||||
b44 = (s[29] << 7) | (s[28] >>> 25);
|
||||
b45 = (s[28] << 7) | (s[29] >>> 25);
|
||||
b26 = (s[38] << 8) | (s[39] >>> 24);
|
||||
b27 = (s[39] << 8) | (s[38] >>> 24);
|
||||
b8 = (s[48] << 14) | (s[49] >>> 18);
|
||||
b9 = (s[49] << 14) | (s[48] >>> 18);
|
||||
s[0] = b0 ^ (~b2 & b4);
|
||||
s[1] = b1 ^ (~b3 & b5);
|
||||
s[10] = b10 ^ (~b12 & b14);
|
||||
s[11] = b11 ^ (~b13 & b15);
|
||||
s[20] = b20 ^ (~b22 & b24);
|
||||
s[21] = b21 ^ (~b23 & b25);
|
||||
s[30] = b30 ^ (~b32 & b34);
|
||||
s[31] = b31 ^ (~b33 & b35);
|
||||
s[40] = b40 ^ (~b42 & b44);
|
||||
s[41] = b41 ^ (~b43 & b45);
|
||||
s[2] = b2 ^ (~b4 & b6);
|
||||
s[3] = b3 ^ (~b5 & b7);
|
||||
s[12] = b12 ^ (~b14 & b16);
|
||||
s[13] = b13 ^ (~b15 & b17);
|
||||
s[22] = b22 ^ (~b24 & b26);
|
||||
s[23] = b23 ^ (~b25 & b27);
|
||||
s[32] = b32 ^ (~b34 & b36);
|
||||
s[33] = b33 ^ (~b35 & b37);
|
||||
s[42] = b42 ^ (~b44 & b46);
|
||||
s[43] = b43 ^ (~b45 & b47);
|
||||
s[4] = b4 ^ (~b6 & b8);
|
||||
s[5] = b5 ^ (~b7 & b9);
|
||||
s[14] = b14 ^ (~b16 & b18);
|
||||
s[15] = b15 ^ (~b17 & b19);
|
||||
s[24] = b24 ^ (~b26 & b28);
|
||||
s[25] = b25 ^ (~b27 & b29);
|
||||
s[34] = b34 ^ (~b36 & b38);
|
||||
s[35] = b35 ^ (~b37 & b39);
|
||||
s[44] = b44 ^ (~b46 & b48);
|
||||
s[45] = b45 ^ (~b47 & b49);
|
||||
s[6] = b6 ^ (~b8 & b0);
|
||||
s[7] = b7 ^ (~b9 & b1);
|
||||
s[16] = b16 ^ (~b18 & b10);
|
||||
s[17] = b17 ^ (~b19 & b11);
|
||||
s[26] = b26 ^ (~b28 & b20);
|
||||
s[27] = b27 ^ (~b29 & b21);
|
||||
s[36] = b36 ^ (~b38 & b30);
|
||||
s[37] = b37 ^ (~b39 & b31);
|
||||
s[46] = b46 ^ (~b48 & b40);
|
||||
s[47] = b47 ^ (~b49 & b41);
|
||||
s[8] = b8 ^ (~b0 & b2);
|
||||
s[9] = b9 ^ (~b1 & b3);
|
||||
s[18] = b18 ^ (~b10 & b12);
|
||||
s[19] = b19 ^ (~b11 & b13);
|
||||
s[28] = b28 ^ (~b20 & b22);
|
||||
s[29] = b29 ^ (~b21 & b23);
|
||||
s[38] = b38 ^ (~b30 & b32);
|
||||
s[39] = b39 ^ (~b31 & b33);
|
||||
s[48] = b48 ^ (~b40 & b42);
|
||||
s[49] = b49 ^ (~b41 & b43);
|
||||
s[0] ^= RC[n];
|
||||
s[1] ^= RC[n + 1];
|
||||
}
|
||||
};
|
||||
|
||||
function WriteNumToArr0(body, Num) {
|
||||
body[0] ^= Num & 0xFF;
|
||||
body[1] ^= (Num >>> 8) & 0xFF;
|
||||
body[2] ^= (Num >>> 16) & 0xFF;
|
||||
body[3] ^= (Num >>> 24) & 0xFF;
|
||||
};
|
||||
|
||||
function ClientHex(Str, nonce) {
|
||||
var arr = [0, 0, 0, 0];
|
||||
for (var i = 0; i < Str.length; i++)
|
||||
arr[4 + i] = Str.charCodeAt(i);
|
||||
WriteNumToArr0(arr, nonce);
|
||||
Mesh(arr, 60);
|
||||
return global.GetHexFromArr(arr) + "-" + nonce;
|
||||
};
|
||||
global.ClientHex = ClientHex;
|
||||
var GlobalCryptID = 0;
|
||||
var DeltaTimeCryptID = new Date(2018, 1, 1) as any - 0;
|
||||
|
||||
function Encrypt(Arr, Arr2, ArrSecret) {
|
||||
const StartLen = 9;
|
||||
var arrRnd: any = Buffer.alloc(StartLen);
|
||||
GlobalCryptID++;
|
||||
arrRnd.writeUInt32LE(GlobalCryptID, 1, 4);
|
||||
var Time = Math.floor((Date.now() - DeltaTimeCryptID) / 1000);
|
||||
arrRnd.writeUInt32LE(Time, 5, 4);
|
||||
Arr2[0] = Arr[0];
|
||||
for (var i = 1; i < StartLen; i++)
|
||||
Arr2[i] = arrRnd[i];
|
||||
var SecretBuf = Buffer.concat([Arr2.slice(0, StartLen), ArrSecret]);
|
||||
DoSecret(Arr, Arr2, SecretBuf, 9);
|
||||
};
|
||||
|
||||
function Decrypt(Arr, Arr2, ArrSecret) {
|
||||
const StartLen = 9;
|
||||
var SecretBuf = Buffer.concat([Arr.slice(0, StartLen), ArrSecret]);
|
||||
DoSecret(Arr, Arr2, SecretBuf, StartLen);
|
||||
};
|
||||
|
||||
function DoSecret(Arr, Arr2, SecretBuf, StartLen) {
|
||||
var CryptID = SecretBuf.readUInt32LE(1, 4);
|
||||
var Pos = StartLen;
|
||||
while (Pos < Arr.length) {
|
||||
var CurBuf = global.shaarr(SecretBuf);
|
||||
for (var i = 0; i < 32 && Pos < Arr.length; i++ , Pos++) {
|
||||
Arr2[Pos] = Arr[Pos] ^ CurBuf[i];
|
||||
}
|
||||
CryptID++;
|
||||
SecretBuf.writeUInt32LE(CryptID, 5, 4);
|
||||
}
|
||||
};
|
||||
|
||||
function TestEncryptDecrypt() {
|
||||
var ArrSecret = Buffer.from([1, 1, 1, 1, 1, 1]);
|
||||
var Arr = GetArrFromStr(" Secret message", 64);
|
||||
var Arr2 = Buffer.from(new Uint8Array(Arr.length));
|
||||
var Arr3 = Buffer.from(new Uint8Array(Arr.length));
|
||||
console.log("Message:");
|
||||
console.log(Arr);
|
||||
console.log("-------------------");
|
||||
Encrypt(Arr, Arr2, ArrSecret);
|
||||
console.log("Encrypt:");
|
||||
console.log(Arr2);
|
||||
console.log("-------------------");
|
||||
Decrypt(Arr2, Arr3, ArrSecret);
|
||||
console.log("Decrypt:");
|
||||
console.log(Utf8ArrayToStr(Arr3.slice(9)));
|
||||
};
|
||||
|
||||
function toUTF8Array(str) {
|
||||
var utf8 = [];
|
||||
for (var i = 0; str && i < str.length; i++) {
|
||||
var charcode = str.charCodeAt(i);
|
||||
if (charcode < 0x80)
|
||||
utf8.push(charcode);
|
||||
else
|
||||
if (charcode < 0x800) {
|
||||
utf8.push(0xc0 | (charcode >> 6), 0x80 | (charcode & 0x3f));
|
||||
}
|
||||
else
|
||||
if (charcode < 0xd800 || charcode >= 0xe000) {
|
||||
utf8.push(0xe0 | (charcode >> 12), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f));
|
||||
}
|
||||
else {
|
||||
i++;
|
||||
charcode = 0x10000 + (((charcode & 0x3ff) << 10) | (str.charCodeAt(i) & 0x3ff));
|
||||
utf8.push(0xf0 | (charcode >> 18), 0x80 | ((charcode >> 12) & 0x3f), 0x80 | ((charcode >> 6) & 0x3f), 0x80 | (charcode & 0x3f));
|
||||
}
|
||||
}
|
||||
return utf8;
|
||||
};
|
||||
|
||||
function Utf8ArrayToStr(array) {
|
||||
var out, i, len, c;
|
||||
var char2, char3;
|
||||
out = "";
|
||||
len = array.length;
|
||||
i = 0;
|
||||
while (i < len) {
|
||||
c = array[i++];
|
||||
switch (c >> 4) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
out += String.fromCharCode(c);
|
||||
break;
|
||||
case 12:
|
||||
case 13:
|
||||
char2 = array[i++];
|
||||
out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
|
||||
break;
|
||||
case 14:
|
||||
char2 = array[i++];
|
||||
char3 = array[i++];
|
||||
out += String.fromCharCode(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (var i: any = 0; i < out.length; i++) {
|
||||
if (out.charCodeAt(i) === 0) {
|
||||
out = out.substr(0, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
};
|
||||
|
||||
function GetArr32FromStr(Str) {
|
||||
return GetArrFromStr(Str, 32);
|
||||
};
|
||||
|
||||
function GetArrFromStr(Str, Len) {
|
||||
var arr = toUTF8Array(Str);
|
||||
for (var i = arr.length; i < Len; i++) {
|
||||
arr[i] = 0;
|
||||
}
|
||||
return arr.slice(0, Len);
|
||||
};
|
||||
global.CalcHash3FromArray = CalcHash3FromArray;
|
||||
global.CalcHashFromArray = CalcHashFromArray;
|
||||
global.CalcMerklFromArray = CalcMerklFromArray;
|
||||
global.CalcTreeHashFromArrBody = CalcTreeHashFromArrBody;
|
||||
global.UpdateMerklTree = UpdateMerklTree;
|
||||
global.GetMerkleProof = GetMerkleProof;
|
||||
global.CheckMerkleProof = CheckMerkleProof;
|
||||
global.IsZeroArr = IsZeroArr;
|
||||
global.GetHashWithNonce = GetHashWithNonce;
|
||||
global.GetPowPower = GetPowPower;
|
||||
global.GetArrFromValue = GetArrFromValue;
|
||||
global.GetPowValue = GetPowValue;
|
||||
global.Mesh = Mesh;
|
||||
global.Encrypt = Encrypt;
|
||||
global.Decrypt = Decrypt;
|
||||
global.toUTF8Array = toUTF8Array;
|
||||
global.Utf8ArrayToStr = Utf8ArrayToStr;
|
||||
global.GetArrFromStr = GetArrFromStr;
|
||||
global.IsDeveloperAccount = function(Key) {
|
||||
for (var i = 0; i < global.DEVELOP_PUB_KEY_ARR.length; i++)
|
||||
if (global.CompareArr(Key, global.DEVELOP_PUB_KEY_ARR[i]) === 0) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.DEVELOP_PUB_KEY_ARR = ["0222263942b11f7a78e11c43903094f870a2bf728bc8be085023b4eaf4e6228cd9", "02250c8c8f7f7e1468cdc5e9b9203841ba14250e2f480f77ebcd502f3e691506d8",
|
||||
"027c0caec4e6f8f08d220f6dab24bb6f53d3f1d7b95231216805d9fac85d34a95f", "025defd5b884cc02f6948cd0d62b03d7b7445bf942206ab935158b6be8f0f7a2ce",
|
||||
"024a97d69cd81c965f162b4b8b7b506263bc8aec8dbcea9eec59f73b5b470a0be1",];
|
||||
let DEVELOP_PUB_KEY_ARR: any = global.DEVELOP_PUB_KEY_ARR;
|
||||
for (var i = 0; i < DEVELOP_PUB_KEY_ARR.length; i++)
|
||||
DEVELOP_PUB_KEY_ARR[i] = Buffer.from(global.GetArrFromHex(DEVELOP_PUB_KEY_ARR[i]));
|
||||
global.DEVELOP_PUB_KEY = DEVELOP_PUB_KEY_ARR[0];
|
||||
global.DEVELOP_PUB_KEY0 = Buffer.from(global.GetArrFromHex("022e80aa78bc07c72781fac12488096f0bfa7b4f48fbab0f2a92e208d1ee3654df"));
|
||||
let LOCAL_RUN = global.LOCAL_RUN;
|
||||
if (LOCAL_RUN) {
|
||||
global.DEVELOP_PUB_KEY0 = Buffer.from(global.GetArrFromHex("026A04AB98D9E4774AD806E302DDDEB63BEA16B5CB5F223EE77478E861BB583EB3"));
|
||||
global.DEVELOP_PUB_KEY = global.DEVELOP_PUB_KEY0;
|
||||
}
|
||||
global.ARR_PUB_KEY = ["027ae0dce92d8be1f893525b226695ddf0fe6ad756349a76777ff51f3b59067d70", "02769165a6f9950d023a415ee668b80bb96b5c9ae2035d97bdfb44f356175a44ff",
|
||||
"021566c6feb5495594fc4bbea27795e1db5a663b3fe81ea9846268d5c394e24c23", "0215accbc993e67216c9b7f3912b29b91671864e861e61ab73589913c946839efa",
|
||||
"0270e0c5acb8eefe7faddac45503da4885e02fb554975d12907f6c33ac6c6bdba5", "0202f2aad628f46d433faf70ba6bf12ab9ed96a46923b592a72508dc43af36cb80",
|
||||
"0254f373fc44ac4a3e80ec8cb8cc3693a856caa82e0493067bdead78ce8ec354b8", "027617f9511b0b0cdbda8f3e17907732731296321846f3fd6fd19460f7227d9482",
|
||||
];
|
||||
let GetHexFromArr = global.GetHexFromArr;
|
||||
if (global.TEST_NETWORK || LOCAL_RUN) {
|
||||
for (var i = 0; i < 100; i++)
|
||||
global.ARR_PUB_KEY[i] = global.GetHexFromArr(global.DEVELOP_PUB_KEY0);
|
||||
global.DEVELOP_PUB_KEY_ARR = [global.DEVELOP_PUB_KEY0];
|
||||
global.DEVELOP_PUB_KEY = DEVELOP_PUB_KEY_ARR[0];
|
||||
}
|
||||
1026
src/core/db/block-db.ts
Normal file
1026
src/core/db/block-db.ts
Normal file
File diff suppressed because it is too large
Load Diff
229
src/core/db/db-row.ts
Normal file
229
src/core/db/db-row.ts
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* @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 * as fs from 'fs'
|
||||
|
||||
module.exports = class CDBState extends require("./db")
|
||||
{
|
||||
private FileName;
|
||||
private DataSize;
|
||||
private Format;
|
||||
private WorkStruct;
|
||||
private FileNameFull;
|
||||
private LastHash;
|
||||
private WasUpdate;
|
||||
private BufMap;
|
||||
private BufMapCount;
|
||||
|
||||
constructor(FileName, DataSize, Format, bReadOnly) {
|
||||
super()
|
||||
this.FileName = FileName
|
||||
this.DataSize = DataSize
|
||||
this.Format = Format
|
||||
this.WorkStruct = {}
|
||||
var FI = this.OpenDBFile(this.FileName, !bReadOnly);
|
||||
this.FileNameFull = FI.fname
|
||||
this.LastHash = undefined
|
||||
this.WasUpdate = 1
|
||||
this.BufMap = {}
|
||||
this.BufMapCount = 0
|
||||
setInterval(this.CheckBufMap.bind(this), 1000)
|
||||
}
|
||||
GetMaxNum() {
|
||||
var FI = this.OpenDBFile(this.FileName);
|
||||
var Num = Math.floor(FI.size / this.DataSize) - 1;
|
||||
return Num;
|
||||
}
|
||||
CheckNewNum(Data) {
|
||||
if (Data.Num === undefined)
|
||||
Data.Num = this.GetMaxNum() + 1
|
||||
}
|
||||
Write(Data, RetBuf) {
|
||||
var startTime = process.hrtime();
|
||||
this.LastHash = undefined
|
||||
this.WasUpdate = 1
|
||||
this.CheckNewNum(Data)
|
||||
Data.Num = Math.trunc(Data.Num)
|
||||
this.DeleteMap(Data.Num)
|
||||
var BufWrite = global.BufLib.GetBufferFromObject(Data, this.Format, this.DataSize, this.WorkStruct, 1);
|
||||
var Position = Data.Num * this.DataSize;
|
||||
var FI = this.OpenDBFile(this.FileName, 1);
|
||||
var written = fs.writeSync(FI.fd, BufWrite, 0, BufWrite.length, Position);
|
||||
if (written !== BufWrite.length) {
|
||||
global.TO_ERROR_LOG("DB-ROW", 10, "Error write to file:" + written + " <> " + BufWrite.length)
|
||||
return false;
|
||||
}
|
||||
if (RetBuf) {
|
||||
RetBuf.Buf = BufWrite
|
||||
}
|
||||
if (Position >= FI.size) {
|
||||
FI.size = Position + this.DataSize
|
||||
}
|
||||
global.ADD_TO_STAT_TIME("ROWS_WRITE_MS", startTime)
|
||||
global.ADD_TO_STAT("ROWS_WRITE")
|
||||
return true;
|
||||
}
|
||||
Read(Num, GetBufOnly?) {
|
||||
Num = Math.trunc(Num)
|
||||
var Data;
|
||||
if (isNaN(Num) || Num < 0 || Num > this.GetMaxNum()) {
|
||||
return undefined;
|
||||
}
|
||||
var BufRead = this.GetMap(Num);
|
||||
if (!BufRead) {
|
||||
BufRead = global.BufLib.GetNewBuffer(this.DataSize)
|
||||
var Position = Num * this.DataSize;
|
||||
var FI = this.OpenDBFile(this.FileName);
|
||||
var bytesRead = fs.readSync(FI.fd, BufRead, 0, BufRead.length, Position);
|
||||
if (bytesRead !== BufRead.length)
|
||||
return undefined;
|
||||
this.SetMap(Num, BufRead)
|
||||
}
|
||||
if (GetBufOnly) {
|
||||
return BufRead;
|
||||
}
|
||||
try {
|
||||
Data = global.BufLib.GetObjectFromBuffer(BufRead, this.Format, this.WorkStruct)
|
||||
}
|
||||
catch (e) {
|
||||
global.ToLog("DBROW:" + e)
|
||||
return undefined;
|
||||
}
|
||||
Data.Num = Num
|
||||
return Data;
|
||||
}
|
||||
GetRows(start, count) {
|
||||
var arr = [];
|
||||
for (var num = start; num < start + count; num++) {
|
||||
var Data = this.Read(num);
|
||||
if (!Data)
|
||||
break;
|
||||
arr.push(Data)
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
Truncate(LastNum) {
|
||||
var startTime = process.hrtime();
|
||||
LastNum = Math.trunc(LastNum)
|
||||
var Position = (LastNum + 1) * this.DataSize;
|
||||
if (Position < 0)
|
||||
Position = 0
|
||||
var FI = this.OpenDBFile(this.FileName, 1);
|
||||
if (Position < FI.size) {
|
||||
this.LastHash = undefined
|
||||
this.WasUpdate = 1
|
||||
if (LastNum < 0)
|
||||
global.ToLog("Truncate " + this.FileName + " from 0", 2)
|
||||
FI.size = Position
|
||||
fs.ftruncateSync(FI.fd, FI.size)
|
||||
this.BufMap = {}
|
||||
this.BufMapCount = 0
|
||||
}
|
||||
global.ADD_TO_STAT_TIME("ROWS_WRITE_MS", startTime)
|
||||
}
|
||||
DeleteHistory(BlockNumFrom) {
|
||||
var MaxNum = this.GetMaxNum();
|
||||
if (MaxNum === - 1)
|
||||
return;
|
||||
for (var num = MaxNum; num >= 0; num--) {
|
||||
var ItemCheck = this.Read(num);
|
||||
if (!ItemCheck)
|
||||
break;
|
||||
if (ItemCheck.BlockNum < BlockNumFrom) {
|
||||
if (num < MaxNum) {
|
||||
this.Truncate(num)
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.Truncate(- 1)
|
||||
}
|
||||
FastFindBlockNum(BlockNum) {
|
||||
var MaxNum = this.GetMaxNum();
|
||||
if (MaxNum === - 1)
|
||||
return;
|
||||
var StartNum = 0;
|
||||
var EndNum = MaxNum;
|
||||
var CurNum = Math.trunc(MaxNum / 2);
|
||||
while (true) {
|
||||
var Item = this.Read(CurNum);
|
||||
if (Item) {
|
||||
if (Item.BlockNum > BlockNum) {
|
||||
EndNum = CurNum - 1
|
||||
var Delta = CurNum - StartNum;
|
||||
if (Delta === 0)
|
||||
return "NoHistory";
|
||||
Delta = Math.trunc((1 + Delta) / 2)
|
||||
CurNum = CurNum - Delta
|
||||
}
|
||||
else
|
||||
if (Item.BlockNum < BlockNum) {
|
||||
StartNum = CurNum + 1
|
||||
var Delta = EndNum - CurNum;
|
||||
if (Delta === 0)
|
||||
return "NoPresent";
|
||||
Delta = Math.trunc((1 + Delta) / 2)
|
||||
CurNum = CurNum + Delta
|
||||
}
|
||||
else
|
||||
if (Item.BlockNum === BlockNum)
|
||||
break;
|
||||
}
|
||||
else {
|
||||
throw "Error read num";
|
||||
return;
|
||||
}
|
||||
}
|
||||
var num = CurNum;
|
||||
while (true) {
|
||||
num--
|
||||
if (num < 0)
|
||||
return CurNum;
|
||||
var Item = this.Read(num);
|
||||
if (Item) {
|
||||
if (Item.BlockNum === BlockNum)
|
||||
CurNum = num
|
||||
else
|
||||
return CurNum;
|
||||
}
|
||||
else {
|
||||
throw "Error read num";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
SetMap(Num, Value) {
|
||||
this.BufMap[Num] = Value
|
||||
this.BufMapCount++
|
||||
}
|
||||
GetMap(Num) {
|
||||
return this.BufMap[Num];
|
||||
}
|
||||
DeleteMap(Num) {
|
||||
if (this.BufMap[Num]) {
|
||||
delete this.BufMap[Num]
|
||||
this.BufMapCount--
|
||||
}
|
||||
}
|
||||
CheckBufMap() {
|
||||
if (this.BufMapCount > 1000) {
|
||||
this.ClearBufMap()
|
||||
}
|
||||
}
|
||||
ClearBufMap() {
|
||||
this.BufMap = {}
|
||||
this.BufMapCount = 0
|
||||
}
|
||||
Close() {
|
||||
this.ClearBufMap()
|
||||
this.CloseDBFile(this.FileName)
|
||||
}
|
||||
};
|
||||
106
src/core/db/db.ts
Normal file
106
src/core/db/db.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* @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 * as fs from 'fs'
|
||||
|
||||
module.exports = class {
|
||||
private DBMap;
|
||||
private LastHash;
|
||||
private WasUpdate;
|
||||
private WasCheckPathDB;
|
||||
|
||||
constructor() {
|
||||
this.DBMap = {}
|
||||
}
|
||||
CheckPathDB() {
|
||||
var Path = global.global.GetDataPath("DB");
|
||||
global.global.CheckCreateDir(Path)
|
||||
}
|
||||
CloseDBFile(name, bdelete) {
|
||||
this.LastHash = undefined
|
||||
this.WasUpdate = 1
|
||||
var Item = this.DBMap[name];
|
||||
if (Item) {
|
||||
let bDelete = bdelete;
|
||||
let Name = name;
|
||||
fs.close(Item.fd, function(err) {
|
||||
if (!err) {
|
||||
if (bDelete) {
|
||||
var fname = global.global.GetDataPath("DB/" + Name);
|
||||
fs.unlink(fname, function(err) {
|
||||
if (err)
|
||||
global.ToLog(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
else {
|
||||
global.ToLog(err)
|
||||
}
|
||||
})
|
||||
delete this.DBMap[name]
|
||||
}
|
||||
}
|
||||
OpenDBFile(name, bWrite, bExist) {
|
||||
if (bWrite && global.READ_ONLY_DB) {
|
||||
global.ToLogTrace("CANNOT WRITE - DB IN READ_ONLY MODE!!!")
|
||||
process.exit()
|
||||
}
|
||||
if (bWrite)
|
||||
CheckStartOneProcess(name + "-run")
|
||||
this.LastHash = undefined
|
||||
this.WasUpdate = 1
|
||||
var Item = this.DBMap[name];
|
||||
if (Item === undefined) {
|
||||
if (!this.WasCheckPathDB) {
|
||||
this.CheckPathDB()
|
||||
this.WasCheckPathDB = true
|
||||
}
|
||||
var fname = global.global.GetDataPath("DB/" + name);
|
||||
if (!fs.existsSync(fname)) {
|
||||
if (bExist) {
|
||||
this.DBMap[name] = null
|
||||
return null;
|
||||
}
|
||||
var fd = fs.openSync(fname, "w+");
|
||||
fs.closeSync(fd)
|
||||
}
|
||||
var fd = fs.openSync(fname, "r+");
|
||||
var stat = fs.statSync(fname);
|
||||
var size = stat.size;
|
||||
Item = { name: name, fname: fname, fd: fd, size: size, FillRows: 0, CountRows: 0, }
|
||||
this.DBMap[name] = Item
|
||||
}
|
||||
return Item;
|
||||
}
|
||||
};
|
||||
var MapCheckProcess = {};
|
||||
var BlockDB = new module.exports();
|
||||
|
||||
function CheckStartOneProcess(Name) {
|
||||
if (global.UpdateMode)
|
||||
return;
|
||||
if (global.READ_ONLY_DB || MapCheckProcess[Name])
|
||||
return;
|
||||
MapCheckProcess[Name] = 1;
|
||||
var path = global.global.GetDataPath("DB/" + Name);
|
||||
if (fs.existsSync(path)) {
|
||||
fs.unlinkSync(path);
|
||||
}
|
||||
try {
|
||||
BlockDB.OpenDBFile(Name);
|
||||
}
|
||||
catch (e) {
|
||||
global.ToLog("****** DETECT START ANOTHER PROCESS for: " + Name);
|
||||
global.ToLogTrace("EXIT");
|
||||
process.exit();
|
||||
}
|
||||
};
|
||||
global.CheckStartOneProcess = CheckStartOneProcess;
|
||||
77
src/core/geo.ts
Normal file
77
src/core/geo.ts
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://t.me/terafoundation
|
||||
*/
|
||||
import * as fs from 'fs'
|
||||
import './library'
|
||||
|
||||
var BufIP;
|
||||
var MapNames = {}, FileIp = "./SITE/DB/iplocation.db", FileNames = "./SITE/DB/locationnames.csv", Format = "{Value:uint32,Length:uint32, id:uint32, latitude:uint32, longitude:uint32}",
|
||||
FormatStruct = {};
|
||||
|
||||
function SetGeoLocation(e) {
|
||||
if (!e.ip || !BufIP || !BufIP.length)
|
||||
return !1;
|
||||
var t = IPToUint(e.ip), i = FindItem(BufIP, 20, t);
|
||||
return i && (e.latitude = i.latitude, e.longitude = i.longitude, e.name = MapNames[i.id]), e.Geo = 1, !0;
|
||||
};
|
||||
|
||||
function ReadItem(e, t) {
|
||||
return BufIP.len = e * t, global.BufLib.Read(BufIP, Format, void 0, FormatStruct);
|
||||
};
|
||||
|
||||
function FindItem(e, t, i) {
|
||||
var n, r = Math.trunc(e.length / t), a = (ReadItem(0, t), ReadItem(r, t), 0), u = r, o = Math.trunc(i * r / 4294967296);
|
||||
r <= o && (o = r - 1), o < a && (o = a);
|
||||
for (var f = 40; 0 < f;) {
|
||||
if (f-- , !(n = ReadItem(o, t)))
|
||||
return void global.ToLog("GEO FindItem - Error read num: " + o);
|
||||
if (n.Value > i) {
|
||||
if (u = o - 1, 0 === (l = o - a))
|
||||
return;
|
||||
o -= l = Math.trunc((1 + l) / 2);
|
||||
}
|
||||
else
|
||||
if (n.Value < i) {
|
||||
if (n.Value + n.Length >= i)
|
||||
return n;
|
||||
var l;
|
||||
if (a = o + 1, 0 === (l = u - o))
|
||||
return;
|
||||
o += l = Math.trunc((1 + l) / 2);
|
||||
}
|
||||
else
|
||||
if (n.Value === i)
|
||||
return n;
|
||||
}
|
||||
};
|
||||
|
||||
function Init() {
|
||||
if (fs.existsSync(FileIp) && fs.existsSync(FileNames)) {
|
||||
BufIP = fs.readFileSync(FileIp);
|
||||
for (var e = fs.readFileSync(FileNames), t = 0; ;) {
|
||||
var i = e.indexOf("\n", t);
|
||||
if (i < 0)
|
||||
break;
|
||||
var n = e.toString("utf-8", t, i - 1);
|
||||
t = i + 1;
|
||||
var r = n.split(","), a = parseInt(r[0]);
|
||||
if (a) {
|
||||
0;
|
||||
var u = r[10];
|
||||
u || (u = r[7]), u || (u = r[5]), MapNames[a] = u;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function IPToUint(e) {
|
||||
var t = e.split(".");
|
||||
return 256 * (256 * (256 * + t[0] + + t[1]) + + t[2]) + + t[3];
|
||||
};
|
||||
global.SetGeoLocation = SetGeoLocation, Init();
|
||||
1710
src/core/html-server.ts
Normal file
1710
src/core/html-server.ts
Normal file
File diff suppressed because it is too large
Load Diff
424
src/core/library.ts
Normal file
424
src/core/library.ts
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://t.me/terafoundation
|
||||
*/
|
||||
import * as fs from 'fs'
|
||||
import * as os from 'os'
|
||||
|
||||
import './constant'
|
||||
import './log'
|
||||
|
||||
let {
|
||||
CONSENSUS_PERIOD_TIME,
|
||||
ToLog,
|
||||
TO_ERROR_LOG,
|
||||
SaveToFile,
|
||||
TimeStart,
|
||||
LOAD_CONST,
|
||||
LoadParams,
|
||||
GetDataPath,
|
||||
CONST_NAME_ARR,
|
||||
SaveParams,
|
||||
SAVE_CONST,
|
||||
GetDeltaCurrentTime,
|
||||
} = global
|
||||
|
||||
Number.prototype.toStringZ = function(count) {
|
||||
var strnum = this.toString();
|
||||
if (strnum.length > count)
|
||||
count = strnum.length;
|
||||
else
|
||||
strnum = "0000000000" + strnum;
|
||||
return strnum.substring(strnum.length - count, strnum.length);
|
||||
};
|
||||
String.prototype.right = function(count) {
|
||||
if (this.length > count)
|
||||
return this.substr(this.length - count, count);
|
||||
else
|
||||
return this.substr(0, this.length);
|
||||
};
|
||||
if (fs.existsSync("./lib/bintrees"))
|
||||
global.RBTree = require("../lib/bintrees").RBTree;
|
||||
else
|
||||
global.RBTree = require('bintrees').RBTree;
|
||||
if (fs.existsSync("./lib/ntp-client"))
|
||||
global.ntpClient = require('../lib/ntp-client');
|
||||
else
|
||||
global.ntpClient = require('ntp-client');
|
||||
global.Stun = require('stun');
|
||||
global.ZIP = require("zip");
|
||||
var strOS = os.platform() + "_" + os.arch();
|
||||
if (global.NWMODE)
|
||||
strOS = strOS + "-nw" + global.NWVERSION;
|
||||
if (fs.existsSync("./lib/secp256k1/" + strOS + "/secp256k1.node")) {
|
||||
try {
|
||||
global.secp256k1 = require('../lib/secp256k1/' + strOS + '/secp256k1.node');
|
||||
}
|
||||
catch (e) {
|
||||
}
|
||||
}
|
||||
if (!global.secp256k1) {
|
||||
global.secp256k1 = require('secp256k1');
|
||||
}
|
||||
require('../HTML/JS/terahashlib.js');
|
||||
require("./crypto-library");
|
||||
if (global.USE_PARAM_JS) {
|
||||
var PathParams = global.GetCodePath("../extern-run.js");
|
||||
if (fs.existsSync(PathParams))
|
||||
try {
|
||||
require(PathParams);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
global.BufLib = require("../core/buffer");
|
||||
require('../HTML/JS/sha3.js');
|
||||
require('../HTML/JS/coinlib.js');
|
||||
global.GetCurrentBlockNumByTime = function GetCurrentBlockNumByTime() {
|
||||
var CurTimeNum = global.GetCurrentTime() - global.FIRST_TIME_BLOCK;
|
||||
var StartBlockNum = Math.trunc((CurTimeNum + CONSENSUS_PERIOD_TIME) / CONSENSUS_PERIOD_TIME);
|
||||
return StartBlockNum;
|
||||
};
|
||||
global.DelDir = function(Path) {
|
||||
if (Path.substr(Path.length - 1, 1) === "/")
|
||||
Path = Path.substr(0, Path.length - 1);
|
||||
if (fs.existsSync(Path)) {
|
||||
var arr = fs.readdirSync(Path);
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var name = Path + "/" + arr[i];
|
||||
if (fs.statSync(name).isDirectory()) {
|
||||
global.DelDir(name);
|
||||
}
|
||||
else {
|
||||
if (name.right(9) == "const.lst")
|
||||
continue;
|
||||
if (name.right(7) == "log.log")
|
||||
continue;
|
||||
fs.unlinkSync(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
global.SliceArr = function(arr, start, end) {
|
||||
var ret = [];
|
||||
for (var i = start; i < end; i++) {
|
||||
ret[i - start] = arr[i];
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
var nRand = Math.floor(123 + Math.random() * 1000);
|
||||
|
||||
function random(max) {
|
||||
return Math.floor(Math.random() * max);
|
||||
};
|
||||
global.random = random;
|
||||
global.AddrLevelArrFromBegin = function(arr1, arr2) {
|
||||
var Level = 0;
|
||||
for (var i = 0; i < arr1.length; i++) {
|
||||
var a1 = arr1[i];
|
||||
var a2 = arr2[i];
|
||||
for (var b = 0; b < 8; b++) {
|
||||
if ((a1 & 128) !== (a2 & 128))
|
||||
return Level;
|
||||
a1 = a1 << 1;
|
||||
a2 = a2 << 1;
|
||||
Level++;
|
||||
}
|
||||
}
|
||||
return Level;
|
||||
};
|
||||
global.AddrLevelArr = function(arr1, arr2) {
|
||||
var Level = 0;
|
||||
for (var i = arr1.length - 1; i >= 0; i--) {
|
||||
var a1 = arr1[i];
|
||||
var a2 = arr2[i];
|
||||
for (var b = 0; b < 8; b++) {
|
||||
if ((a1 & 1) !== (a2 & 1))
|
||||
return Level;
|
||||
a1 = a1 >> 1;
|
||||
a2 = a2 >> 1;
|
||||
Level++;
|
||||
}
|
||||
}
|
||||
return Level;
|
||||
};
|
||||
global.SaveToFile = function(name, buf) {
|
||||
var fs = require('fs');
|
||||
var file_handle = fs.openSync(name, "w");
|
||||
fs.writeSync(file_handle, buf, 0, buf.length);
|
||||
fs.closeSync(file_handle);
|
||||
};
|
||||
global.LoadParams = function(filename, DefaultValue) {
|
||||
try {
|
||||
if (fs.existsSync(filename)) {
|
||||
var Str = fs.readFileSync(filename);
|
||||
if (Str.length > 0)
|
||||
return JSON.parse(Str as any);
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
TO_ERROR_LOG("MAINLIB", 100, "Error in file:" + filename + "\n" + err);
|
||||
}
|
||||
return DefaultValue;
|
||||
};
|
||||
global.SaveParams = function(filename, data) {
|
||||
SaveToFile(filename, Buffer.from(JSON.stringify(data, undefined, 4)));
|
||||
};
|
||||
global.StartTime = function() {
|
||||
global.TimeStart = global.GetCurrentTime();
|
||||
};
|
||||
global.FinishTime = function(Str) {
|
||||
Str = Str || "";
|
||||
var TimeFinish = global.GetCurrentTime();
|
||||
var delta = TimeFinish - TimeStart;
|
||||
console.log(Str + " time: " + delta + " ms");
|
||||
};
|
||||
global.CompareItemBufFD = function(a, b) {
|
||||
if (a.FD !== b.FD)
|
||||
return a.FD - b.FD;
|
||||
else
|
||||
return a.Position - b.Position;
|
||||
};
|
||||
global.CompareArr33 = function(a, b) {
|
||||
for (var i = 0; i < 33; i++) {
|
||||
if (a[i] !== b[i])
|
||||
return a[i] - b[i];
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.CompareItemHashSimple = function(a, b) {
|
||||
if (a.hash < b.hash)
|
||||
return - 1;
|
||||
else
|
||||
if (a.hash > b.hash)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
global.CompareItemHash = function(a, b) {
|
||||
var hasha = a.hash;
|
||||
var hashb = b.hash;
|
||||
for (var i = 0; i < hasha.length; i++) {
|
||||
if (hasha[i] !== hashb[i])
|
||||
return hasha[i] - hashb[i];
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.CompareItemHash32 = function(a, b) {
|
||||
var hasha = a.hash;
|
||||
var hashb = b.hash;
|
||||
for (var i = 0; i < 32; i++) {
|
||||
if (hasha[i] !== hashb[i])
|
||||
return hasha[i] - hashb[i];
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.CompareItemHASH32 = function(a, b) {
|
||||
var hasha = a.HASH;
|
||||
var hashb = b.HASH;
|
||||
for (var i = 0; i < 32; i++) {
|
||||
if (hasha[i] !== hashb[i])
|
||||
return hasha[i] - hashb[i];
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.CompareItemHash33 = function(a, b) {
|
||||
var hasha = a.hash;
|
||||
var hashb = b.hash;
|
||||
for (var i = 0; i < 33; i++) {
|
||||
if (hasha[i] !== hashb[i])
|
||||
return hasha[i] - hashb[i];
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
global.CompareItemHashPow = function(a, b) {
|
||||
return global.CompareArr(a.HashPow, b.HashPow);
|
||||
};
|
||||
global.CompareItemTimePow = function(a, b) {
|
||||
if (b.TimePow !== a.TimePow)
|
||||
return b.TimePow - a.TimePow;
|
||||
else
|
||||
return global.CompareArr(a.HashPow, b.HashPow);
|
||||
};
|
||||
global.LOAD_CONST = function() {
|
||||
var Count = 0;
|
||||
var constants = LoadParams(global.GetDataPath("const.lst"), {});
|
||||
if (constants) {
|
||||
for (var i = 0; i < CONST_NAME_ARR.length; i++) {
|
||||
var key = CONST_NAME_ARR[i];
|
||||
if (constants[key] !== undefined) {
|
||||
Count++;
|
||||
global[key] = constants[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return Count;
|
||||
};
|
||||
var WasStartSaveConst = false;
|
||||
|
||||
function SaveConst() {
|
||||
var constants = {};
|
||||
for (var i = 0; i < CONST_NAME_ARR.length; i++) {
|
||||
var key = CONST_NAME_ARR[i];
|
||||
if (global[key] !== undefined)
|
||||
constants[key] = global[key];
|
||||
}
|
||||
SaveParams(global.GetDataPath("const.lst"), constants);
|
||||
WasStartSaveConst = false;
|
||||
};
|
||||
global.SAVE_CONST = function(bForce) {
|
||||
if (bForce) {
|
||||
SaveConst();
|
||||
}
|
||||
else {
|
||||
if (!WasStartSaveConst)
|
||||
setTimeout(SaveConst, 10 * 1000);
|
||||
WasStartSaveConst = true;
|
||||
}
|
||||
};
|
||||
|
||||
function CheckGlobalTime() {
|
||||
global.ntpClient.getNetworkTime("pool.ntp.org", 123, function(err, NetTime) {
|
||||
if (err) {
|
||||
TO_ERROR_LOG("MAINLIB", 110, err);
|
||||
return;
|
||||
}
|
||||
var curTime = new Date;
|
||||
global.DELTA_CURRENT_TIME = NetTime - (curTime as any);
|
||||
if (isNaN(global.DELTA_CURRENT_TIME) || typeof global.DELTA_CURRENT_TIME !== "number")
|
||||
global.DELTA_CURRENT_TIME = 0;
|
||||
else
|
||||
if (Math.abs(global.DELTA_CURRENT_TIME) > 24 * 3600 * 1000)
|
||||
global.DELTA_CURRENT_TIME = 0;
|
||||
global.ToLog("Get global time: " + NetTime);
|
||||
SAVE_CONST();
|
||||
});
|
||||
SAVE_CONST();
|
||||
};
|
||||
global.CheckGlobalTime = CheckGlobalTime;
|
||||
global.GetDeltaCurrentTime = function() {
|
||||
if (isNaN(global.DELTA_CURRENT_TIME) || typeof global.DELTA_CURRENT_TIME !== "number")
|
||||
global.DELTA_CURRENT_TIME = 0;
|
||||
return global.DELTA_CURRENT_TIME;
|
||||
};
|
||||
global.GetStrTimeUTC = function(now) {
|
||||
if (!global.GetCurrentTime)
|
||||
return ":::";
|
||||
if (!now)
|
||||
now = global.GetCurrentTime();
|
||||
var Str = "" + now.getUTCDate();
|
||||
Str = Str + "." + (1 + now.getUTCMonth());
|
||||
Str = Str + "." + now.getUTCFullYear();
|
||||
Str = Str + " " + now.getUTCHours();
|
||||
Str = Str + ":" + now.getUTCMinutes();
|
||||
Str = Str + ":" + now.getUTCSeconds();
|
||||
return Str;
|
||||
};
|
||||
global.GetStrOnlyTimeUTC = function(now) {
|
||||
if (!global.GetCurrentTime)
|
||||
return ":::";
|
||||
if (!now)
|
||||
now = global.GetCurrentTime();
|
||||
var Str;
|
||||
Str = "" + now.getUTCHours().toStringZ(2);
|
||||
Str = Str + ":" + now.getUTCMinutes().toStringZ(2);
|
||||
Str = Str + ":" + now.getUTCSeconds().toStringZ(2);
|
||||
return Str;
|
||||
};
|
||||
|
||||
function GetSecFromStrTime(Str) {
|
||||
var arr = Str.split(":");
|
||||
var Mult = 3600;
|
||||
var Sum = 0;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
Sum += Mult * parseInt(arr[i]);
|
||||
Mult = Mult / 60;
|
||||
}
|
||||
return Sum;
|
||||
};
|
||||
global.GetSecFromStrTime = GetSecFromStrTime;
|
||||
global.GetCurrentTime = function(Delta_Time) {
|
||||
if (Delta_Time === undefined)
|
||||
Delta_Time = GetDeltaCurrentTime();
|
||||
var curTime: any = new Date;
|
||||
var Time = new Date(curTime - (- Delta_Time));
|
||||
return Time;
|
||||
};
|
||||
|
||||
function DateFromBlock(BlockNum) {
|
||||
var Str;
|
||||
var now = new Date(global.FIRST_TIME_BLOCK + BlockNum * 1000);
|
||||
Str = now.toISOString();
|
||||
Str = Str.substr(0, Str.indexOf("."));
|
||||
Str = Str.replace("T", " ");
|
||||
return Str;
|
||||
};
|
||||
global.DateFromBlock = DateFromBlock;
|
||||
var code_base = ' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\u0402\u0403\u201a\u0453\u201e\u2026\u2020\u2021\u20ac\u2030\u0409\u2039\u040a\u040c\u040b\u040f\u0452\u2018\u2019\u201c\u201d\u2022\u2013\u2014\ufffd\u2122\u0459\u203a\u045a\u045c\u045b\u045f\xa0\u040e\u045e\u0408\xa4\u0490\xa6\xa7\u0401\xa9\u0404\xab\xac\xad\xae\u0407\xb0\xb1\u0406\u0456\u0491\xb5\xb6\xb7\u0451\u2116\u0454\xbb\u0458\u0405\u0455\u0457\u0410\u0411\u0412\u0413\u0414\u0415\u0416\u0417\u0418\u0419\u041a\u041b\u041c\u041d\u041e\u041f\u0420\u0421\u0422\u0423\u0424\u0425\u0426\u0427\u0428\u0429\u042a\u042b\u042c\u042d\u042e\u042f\u0430\u0431\u0432\u0433\u0434\u0435\u0436\u0437\u0438\u0439\u043a\u043b\u043c\u043d\u043e\u043f\u0440\u0441\u0442\u0443\u0444\u0445\u0446\u0447\u0448\u0449\u044a\u044b\u044c\u044d\u044e\u044f';
|
||||
global.NormalizeName = function(Name) {
|
||||
var Str = "";
|
||||
for (var i = 0; i < Name.length; i++) {
|
||||
var code = Name.charCodeAt(i);
|
||||
if (code >= 32)
|
||||
Str += code_base.charAt(code - 32);
|
||||
}
|
||||
return Str;
|
||||
};
|
||||
var glEvalMap = {};
|
||||
|
||||
function CreateEval(formula, StrParams) {
|
||||
var Ret = glEvalMap[formula];
|
||||
if (!Ret) {
|
||||
eval("function M(" + StrParams + "){return " + formula + "}; Ret=M;");
|
||||
glEvalMap[formula] = Ret;
|
||||
}
|
||||
return Ret;
|
||||
};
|
||||
global.CreateEval = CreateEval;
|
||||
var CPU_Count = os.cpus().length;
|
||||
|
||||
function GetCountMiningCPU() {
|
||||
if (global.COUNT_MINING_CPU)
|
||||
return global.COUNT_MINING_CPU;
|
||||
else {
|
||||
return CPU_Count - 1;
|
||||
}
|
||||
};
|
||||
global.GetCountMiningCPU = GetCountMiningCPU;
|
||||
var AddTrMap = [];
|
||||
AddTrMap[- 6] = "Inner node error";
|
||||
AddTrMap[- 5] = "Bad block num";
|
||||
AddTrMap[- 4] = "Bad type transaction";
|
||||
AddTrMap[- 3] = "Bad time";
|
||||
AddTrMap[- 2] = "Bad PoW";
|
||||
AddTrMap[- 1] = "Bad length";
|
||||
AddTrMap[0] = "Not add";
|
||||
AddTrMap[1] = "OK";
|
||||
AddTrMap[2] = "Update OK";
|
||||
AddTrMap[3] = "Was send";
|
||||
AddTrMap[4] = "Added to timer";
|
||||
global.AddTrMap = AddTrMap;
|
||||
|
||||
function GrayConnect() {
|
||||
if (global.NET_WORK_MODE && !global.NET_WORK_MODE.UseDirectIP)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
};
|
||||
global.GrayConnect = GrayConnect;
|
||||
var ResConst = LOAD_CONST();
|
||||
if (global.START_SERVER) {
|
||||
if (!ResConst) {
|
||||
CheckGlobalTime();
|
||||
}
|
||||
else
|
||||
if (global.CHECK_GLOBAL_TIME) {
|
||||
CheckGlobalTime();
|
||||
}
|
||||
}
|
||||
36
src/core/log-strict.ts
Normal file
36
src/core/log-strict.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://t.me/terafoundation
|
||||
*/
|
||||
import * as fs from 'fs'
|
||||
|
||||
let {
|
||||
ToLog,
|
||||
MAX_SIZE_LOG
|
||||
} = global
|
||||
|
||||
function CheckSizeLogFile(file_name, file_name_prev) {
|
||||
"use strict";
|
||||
let FILE_NAME_LOG = file_name;
|
||||
let FILE_NAME_LOG_PREV = file_name_prev;
|
||||
setInterval(function() {
|
||||
try {
|
||||
var stat = fs.statSync(FILE_NAME_LOG);
|
||||
if (stat.size > MAX_SIZE_LOG) {
|
||||
if (fs.existsSync(FILE_NAME_LOG_PREV)) {
|
||||
fs.unlinkSync(FILE_NAME_LOG_PREV);
|
||||
}
|
||||
fs.renameSync(FILE_NAME_LOG, FILE_NAME_LOG_PREV);
|
||||
global.ToLog("truncate logfile ok");
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
}
|
||||
}, 60000);
|
||||
};
|
||||
global.CheckSizeLogFile = CheckSizeLogFile;
|
||||
237
src/core/log.ts
Normal file
237
src/core/log.ts
Normal file
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://t.me/terafoundation
|
||||
*/
|
||||
import * as fs from 'fs'
|
||||
|
||||
import './constant'
|
||||
import './log-strict'
|
||||
|
||||
let {
|
||||
GetDataPath,
|
||||
START_PORT_NUMBER,
|
||||
CheckSizeLogFile,
|
||||
ToError,
|
||||
ToLog,
|
||||
GetCurrentTime,
|
||||
DEBUG_MODE,
|
||||
SERVER
|
||||
} = global
|
||||
|
||||
var file_name_info = global.GetDataPath("info.log"), file_name_infoPrev = global.GetDataPath("info-prev.log");
|
||||
CheckSizeLogFile(file_name_info, file_name_infoPrev);
|
||||
var file_name_log = global.GetDataPath("log.log"), file_name_logPrev = global.GetDataPath("log-prev.log");
|
||||
CheckSizeLogFile(file_name_log, file_name_logPrev);
|
||||
var file_name_log_web = global.GetDataPath("web.log"), file_name_log_webPrev = global.GetDataPath("web-prev.log");
|
||||
CheckSizeLogFile(file_name_log_web, file_name_log_webPrev);
|
||||
var StartStatTime, file_name_error = global.GetDataPath("err.log"), file_name_errorPrev = global.GetDataPath("err-prev.log");
|
||||
|
||||
function ToLogFile(e, t, r?) {
|
||||
t instanceof Error && (t = t.message + "\n" + t.stack), global.START_SERVER || (t = global.PROCESS_NAME + ": " + t), "MAIN" !== global.PROCESS_NAME && process.send ? process.send({
|
||||
cmd: "log",
|
||||
message: t
|
||||
}) : (console.log(START_PORT_NUMBER + ": " + global.GetStrOnlyTime() + ": " + t), r || SaveToLogFileSync(e, t));
|
||||
};
|
||||
|
||||
function ToLogClient(e, t, r) {
|
||||
let ArrLogClient = global.ArrLogClient;
|
||||
e && (ToLogFile(file_name_log, e), t || (t = ""), ArrLogClient.push({ text: global.GetStrOnlyTime() + " " + e, key: t, final: r }), 13 < ArrLogClient.length && ArrLogClient.shift());
|
||||
};
|
||||
CheckSizeLogFile(file_name_error, file_name_errorPrev), global.ToLog = function(e, t) {
|
||||
void 0 === t && (t = 1), t && t > global.LOG_LEVEL || (global.ALL_LOG_TO_CLIENT ? ToLogClient(e, void 0, void 0) : ToLogFile(file_name_log,
|
||||
e));
|
||||
}, global.ToLogWeb = function(e) {
|
||||
}, global.SmallAddr = function(e) {
|
||||
return e.substr(0, 5);
|
||||
}, global.ToErrorTrace = function(e) {
|
||||
global.ToError(e + ":" + (new Error).stack);
|
||||
}, global.ToLogTrace = function(e) {
|
||||
global.ToErrorTrace(e);
|
||||
}, global.ToInfo = function(e) {
|
||||
ToLogFile(file_name_info, e, 1);
|
||||
}, global.ToError = function(e) {
|
||||
ToLogFile(file_name_error, e);
|
||||
}, global.ArrLogClient = [], global.ToLogClient = ToLogClient, global.ToLogClient0 = ToLogClient;
|
||||
var CONTEXT_STATS = { Total: {}, Interval: [] }, CONTEXT_ERRORS = { Total: {}, Interval: [] }, CurStatIndex = 0;
|
||||
let MAX_STAT_PERIOD = global.MAX_STAT_PERIOD;
|
||||
function GetCurrentStatIndex() {
|
||||
var e = 2 * MAX_STAT_PERIOD + 2;
|
||||
return CurStatIndex % e;
|
||||
};
|
||||
|
||||
function ResizeArrMax(e) {
|
||||
for (var t = [], r = Math.trunc(e.length / 2), o = 0; o < r; o++)
|
||||
t[o] = Math.max(e[2 * o], e[2 * o + 1]);
|
||||
return t;
|
||||
};
|
||||
|
||||
function ResizeArrAvg(e) {
|
||||
for (var t = [], r = Math.trunc(e.length / 2), o = 0; o < r; o++)
|
||||
t[o] = (e[2 * o] + e[2 * o + 1]) / 2;
|
||||
return t;
|
||||
};
|
||||
|
||||
function ResizeArr(e) {
|
||||
for (var t = [], r = Math.trunc(e.length / 2), o = 0; o < r; o++)
|
||||
t[o] = e[2 * o];
|
||||
return t;
|
||||
};
|
||||
|
||||
function GetDiagramData(e, t) {
|
||||
var r, o = 2 * MAX_STAT_PERIOD + 2;
|
||||
r = "MAX:" === t.substr(0, 4);
|
||||
for (var n, a = MAX_STAT_PERIOD, l = (GetCurrentStatIndex() - a + o) % o, i = (e.Total, []), T = void 0, g = l; g < l + a; g++) {
|
||||
var S = g % o;
|
||||
if (n = e.Interval[S]) {
|
||||
var _ = n[t];
|
||||
void 0 !== _ ? r ? i.push(_) : (void 0 !== T ? i.push(_ - T) : i.push(_), T = _) : i.push(0);
|
||||
}
|
||||
}
|
||||
return i;
|
||||
};
|
||||
|
||||
function CalcInterval(e, t, r) {
|
||||
for (var o, n = 2 * MAX_STAT_PERIOD + 2, a = {}, l = (t - r + n) % n, i = e.Total, T = l; T < l + r; T++) {
|
||||
var g = T % n;
|
||||
if (o = e.Interval[g])
|
||||
break;
|
||||
}
|
||||
if (o)
|
||||
for (var S in i)
|
||||
"MAX:" === S.substr(0, 4) ? a[S] = 0 : void 0 === o[S] ? a[S] = i[S] : a[S] = i[S] - o[S];
|
||||
return a;
|
||||
};
|
||||
|
||||
function AddToStatContext(e, t, r?) {
|
||||
void 0 === r && (r = 1);
|
||||
var o = e.Total[t];
|
||||
o || (o = 0), "MAX:" === t.substr(0, 4) ? o = Math.max(o, r) : o += r, e.Total[t] = o, StartStatTime || (StartStatTime = global.GetStrOnlyTime(0));
|
||||
};
|
||||
|
||||
function CopyStatInterval(e, t) {
|
||||
var r = e.Interval[t];
|
||||
r || (r = {}, e.Interval[t] = r);
|
||||
var o = e.Total;
|
||||
for (var n in o)
|
||||
r[n] = o[n], "MAX:" === n.substr(0, 4) && (o[n] = 0);
|
||||
};
|
||||
|
||||
function SaveToLogFileAsync(e, o) {
|
||||
fs.open(e, "a", void 0, function(e, r) {
|
||||
if (e)
|
||||
console.log("Ошибка открытия лог-файла ошибок");
|
||||
else {
|
||||
var t = global.GetStrTime() + " : " + o + "\r\n";
|
||||
fs.write(r, t, null, "utf8", function(e, t) {
|
||||
e ? console.log("Ошибка записи в лог-файл ошибок!") : fs.close(r, function(e) {
|
||||
e && console.log(e);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function SaveToLogFileSync(e, t) {
|
||||
try {
|
||||
var r = global.GetStrTime() + " : " + t + "\r\n", o = fs.openSync(e, "a");
|
||||
fs.writeSync(o, r, null, "utf8"), fs.closeSync(o);
|
||||
}
|
||||
catch (e) {
|
||||
console.log(e.message);
|
||||
}
|
||||
};
|
||||
global.PrepareStatEverySecond = function() {
|
||||
CurStatIndex++;
|
||||
var e = GetCurrentStatIndex();
|
||||
CopyStatInterval(CONTEXT_STATS, e), CopyStatInterval(CONTEXT_ERRORS, e);
|
||||
}, global.TO_ERROR_LOG = function(e, t, r, o, n, a) {
|
||||
r instanceof Error && (r = r.message + "\n"), "rinfo" === o ? r += " from: " + n.address + ":" + n.port : "node" === o && (r += " from: " + n.ip + ":" + n.port);
|
||||
var l = e + ":" + t;
|
||||
global.ToError(" ==ERROR== " + l + " " + r), AddToStatContext(CONTEXT_ERRORS, l), global.ADD_TO_STAT("ERRORS");
|
||||
}, global.HASH_RATE = 0, global.ADD_HASH_RATE = function(e) {
|
||||
e /= 1e6, global.HASH_RATE += e, global.ADD_TO_STAT("HASHRATE", e);
|
||||
}, global.GET_STAT = function(e) {
|
||||
var t = CONTEXT_STATS.Total[e];
|
||||
return t || (t = 0), t;
|
||||
}, global.ADD_TO_STAT_TIME = function(e, t, r) {
|
||||
if (global.STAT_MODE) {
|
||||
if (r && 2 !== global.STAT_MODE)
|
||||
return;
|
||||
var o = process.hrtime(t), n = 1e3 * o[0] + o[1] / 1e6;
|
||||
global.ADD_TO_STAT(e, n);
|
||||
}
|
||||
}, global.ADD_TO_STAT = function(e, t, r) {
|
||||
if (global.STAT_MODE) {
|
||||
if (r && 2 !== global.STAT_MODE)
|
||||
return;
|
||||
AddToStatContext(CONTEXT_STATS, e, t);
|
||||
}
|
||||
}, global.GET_STATDIAGRAMS = function(e) {
|
||||
GetCurrentTime();
|
||||
var t = GetCurrentStatIndex();
|
||||
if (!e || !e.length)
|
||||
return [];
|
||||
for (var r = [], o = 0; o < e.length; o++) {
|
||||
var n = e[o], a = GetDiagramData(CONTEXT_STATS, n);
|
||||
r.push({ name: n, maxindex: t, arr: a, starttime: StartStatTime - 0, steptime: 1 });
|
||||
}
|
||||
var l = void 0;
|
||||
for (o = 0; o < r.length; o++) {
|
||||
0 < (T = r[o].arr).length && (void 0 === l || T.length < l) && (l = T.length);
|
||||
}
|
||||
for (o = 0; o < r.length; o++) {
|
||||
var i = r[o], T = i.arr;
|
||||
l && T.length > l && (T = T.slice(T.length - l)), l && 0 <= ",POWER_MY_WIN,POWER_BLOCKCHAIN,".indexOf("," + i.name + ",") && (T = global.SERVER.GetStatBlockchain(i.name,
|
||||
l));
|
||||
for (var g = 0, S = 0; S < T.length; S++)
|
||||
T[S] && (g += T[S]);
|
||||
0 < T.length && (g /= T.length);
|
||||
var _ = 1;
|
||||
if ("MAX:" === i.name.substr(0, 4))
|
||||
for (; 500 <= T.length;)
|
||||
T = ResizeArrMax(T), _ *= 2;
|
||||
else
|
||||
for (; 500 <= T.length;)
|
||||
T = ResizeArrAvg(T), _ *= 2;
|
||||
i.AvgValue = g, i.steptime = _, i.arr = T.slice(1);
|
||||
}
|
||||
return r;
|
||||
}, global.GET_STATS = function(e) {
|
||||
var t = global.GetCurrentTime(), r = GetCurrentStatIndex();
|
||||
return {
|
||||
stats: {
|
||||
Counter: CONTEXT_STATS.Total, Counter10S: CalcInterval(CONTEXT_STATS, r, 10), Counter10M: CalcInterval(CONTEXT_STATS,
|
||||
r, 600)
|
||||
}, errors: {
|
||||
Counter: CONTEXT_ERRORS.Total, Counter10S: CalcInterval(CONTEXT_ERRORS, r, 10), Counter10M: CalcInterval(CONTEXT_ERRORS,
|
||||
r, 600)
|
||||
}, period: (t - StartStatTime) / 1e3, Confirmation: []
|
||||
};
|
||||
}, global.StartCommonStat = function() {
|
||||
for (var e in CONTEXT_STATS.Total)
|
||||
return;
|
||||
global.ClearCommonStat();
|
||||
}, global.ClearCommonStat = function() {
|
||||
StartStatTime = void (CurStatIndex = 0), CONTEXT_STATS = { Total: {}, Interval: [] }, CONTEXT_ERRORS = { Total: {}, Interval: [] },
|
||||
global.HASH_RATE = 0, global.SERVER.ClearStat();
|
||||
}, global.ResizeArrAvg = ResizeArrAvg, global.ResizeArrMax = ResizeArrMax, DEBUG_MODE ? global.TO_DEBUG_LOG = function(e, t, r, o) {
|
||||
DEBUG_MODE && ("rinfo" === t && (e += " from: " + r.address + ":" + r.port + " - " + o.length), global.ToLog(e));
|
||||
} : global.TO_DEBUG_LOG = function(e, t, r, o) {
|
||||
}, global.GetStrOnlyTime = function(e) {
|
||||
if (!global.GetCurrentTime)
|
||||
return ":::";
|
||||
e || (e = global.GetCurrentTime());
|
||||
var t = "" + e.getHours().toStringZ(2);
|
||||
return t = (t = (t = t + ":" + e.getMinutes().toStringZ(2)) + ":" + e.getSeconds().toStringZ(2)) + "." + e.getMilliseconds().toStringZ(3);
|
||||
}, global.GetStrTime = function(e) {
|
||||
if (!global.GetCurrentTime)
|
||||
return ":::";
|
||||
e || (e = global.GetCurrentTime());
|
||||
var t = "" + e.getDate().toStringZ(2);
|
||||
return t = (t = (t = (t = (t = (t = t + "." + (1 + e.getMonth()).toStringZ(2)) + "." + e.getFullYear()) + " " + e.getHours().toStringZ(2)) + ":" + e.getMinutes().toStringZ(2)) + ":" + e.getSeconds().toStringZ(2)) + "." + e.getMilliseconds().toStringZ(3);
|
||||
};
|
||||
598
src/core/node.ts
Normal file
598
src/core/node.ts
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* @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";
|
||||
require("./library.js");
|
||||
const net = require("net");
|
||||
var ConnectIDCount = 1;
|
||||
module.exports = class CNode {
|
||||
addrStr
|
||||
ip
|
||||
port
|
||||
StartFindList
|
||||
WhiteConnect
|
||||
GrayConnect
|
||||
POW
|
||||
FirstTime
|
||||
FirstTimeStr
|
||||
LastTime
|
||||
LastTimeError
|
||||
LastTimeTransfer
|
||||
FromIP
|
||||
FromPort
|
||||
Active
|
||||
Hot
|
||||
CanHot
|
||||
CountChildConnect
|
||||
BlockProcessCount
|
||||
VersionOK
|
||||
VersionNum
|
||||
Delete
|
||||
DeltaBan
|
||||
Name
|
||||
Info
|
||||
PrevInfo
|
||||
StartTimeHot
|
||||
NextHotDelta
|
||||
LastTimeGetNode
|
||||
DeltaGlobTime
|
||||
CountDeltaTime
|
||||
DeltaTime
|
||||
SumDeltaTime
|
||||
TransferCount
|
||||
StopGetBlock
|
||||
LevelCount
|
||||
LevelEnum
|
||||
TimeMap
|
||||
bInit
|
||||
INFO
|
||||
DoubleConnectCount
|
||||
StartTimeConnect
|
||||
NextConnectDelta
|
||||
StartTimeGetNodes
|
||||
NextGetNodesDelta
|
||||
PingStart
|
||||
NextPing
|
||||
SendBlockArr
|
||||
LoadBlockArr
|
||||
SendBlockCount
|
||||
LoadBlockCount
|
||||
SendBlockCountAll
|
||||
LoadBlockCountAll
|
||||
WantHardTrafficArr
|
||||
WantHardTraffic
|
||||
CanHardTraffic
|
||||
BufWriteLength
|
||||
BufWrite
|
||||
SendPacket
|
||||
ConnectCount
|
||||
TrafficArr
|
||||
SendTrafficCurrent
|
||||
SendTrafficLimit
|
||||
ErrCount
|
||||
ErrCountAll
|
||||
SendPacketNum
|
||||
Socket
|
||||
Socket2
|
||||
constructor(addrStr, ip, port) {
|
||||
this.addrStr = addrStr
|
||||
this.ip = ip.trim()
|
||||
this.port = port
|
||||
this.StartFindList = 0
|
||||
this.WhiteConnect = 0
|
||||
this.GrayConnect = 0
|
||||
this.POW = 0
|
||||
this.FirstTime = 0
|
||||
this.FirstTimeStr = ""
|
||||
this.LastTime = 0
|
||||
this.LastTimeError = 0
|
||||
this.LastTimeTransfer = 0
|
||||
this.FromIP = undefined
|
||||
this.FromPort = undefined
|
||||
this.Active = false
|
||||
this.Hot = false
|
||||
this.CanHot = false
|
||||
this.CountChildConnect = 0
|
||||
this.BlockProcessCount = 0
|
||||
this.VersionOK = false
|
||||
this.VersionNum = 0
|
||||
this.Delete = 0
|
||||
this.DeltaBan = 300
|
||||
this.Name = ""
|
||||
this.Info = ""
|
||||
this.PrevInfo = ""
|
||||
this.StartTimeHot = 0
|
||||
this.NextHotDelta = 1000
|
||||
this.ResetNode()
|
||||
}
|
||||
ResetNode() {
|
||||
this.LastTimeGetNode = 0
|
||||
this.DeltaGlobTime = 0
|
||||
this.CountDeltaTime = 0
|
||||
this.DeltaTime = 1000
|
||||
this.SumDeltaTime = 0
|
||||
this.TransferCount = 0
|
||||
this.StopGetBlock = 0
|
||||
this.LevelCount = 0
|
||||
this.LevelEnum = 100
|
||||
this.TimeMap = {}
|
||||
this.bInit = 1
|
||||
this.INFO = {}
|
||||
this.DoubleConnectCount = 0
|
||||
this.StartTimeConnect = 0
|
||||
this.NextConnectDelta = 1000
|
||||
this.StartTimeGetNodes = 0
|
||||
this.NextGetNodesDelta = 1000
|
||||
this.PingStart = 0
|
||||
this.NextPing = MIN_PERIOD_PING
|
||||
this.SendBlockArr = []
|
||||
this.LoadBlockArr = []
|
||||
this.SendBlockCount = 0
|
||||
this.LoadBlockCount = 0
|
||||
this.SendBlockCountAll = 0
|
||||
this.LoadBlockCountAll = 0
|
||||
this.WantHardTrafficArr = []
|
||||
this.WantHardTraffic = 0
|
||||
this.CanHardTraffic = 0
|
||||
this.BufWriteLength = 0
|
||||
this.BufWrite = Buffer.alloc(0)
|
||||
this.SendPacket = new RBTree(function(a, b) {
|
||||
return b.PacketNum - a.PacketNum;
|
||||
})
|
||||
this.ConnectCount = 0
|
||||
this.TrafficArr = []
|
||||
this.SendTrafficCurrent = 0
|
||||
this.SendTrafficLimit = 0
|
||||
this.ErrCount = 0
|
||||
this.ErrCountAll = 0
|
||||
var Prioritet = this.BlockProcessCount;
|
||||
global.SERVER.SetNodePrioritet(this, Prioritet)
|
||||
this.SendPacketNum = 0
|
||||
}
|
||||
ConnectStatus() {
|
||||
if (this.Socket)
|
||||
return GetSocketStatus(this.Socket);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
CreateConnect() {
|
||||
delete global.SERVER.BAN_IP[this.ip]
|
||||
let NODE = this;
|
||||
if (NODE.ConnectStatus()) {
|
||||
if (NODE.ConnectStatus() === 100)
|
||||
global.SERVER.AddNodeToActive(NODE)
|
||||
return;
|
||||
}
|
||||
global.AddNodeInfo(NODE, "===CreateConnect===")
|
||||
global.CloseSocket(NODE.Socket, "CreateConnect")
|
||||
NODE.SocketStart = Date.now()
|
||||
NODE.Socket = net.createConnection(NODE.port, NODE.ip, function() {
|
||||
if (NODE.Socket) {
|
||||
socketInit(NODE.Socket, "s")
|
||||
global.AddNodeInfo(NODE, "OK connected *" + NODE.Socket.ConnectID)
|
||||
NODE.Socket.ConnectToServer = true
|
||||
SetSocketStatus(NODE.Socket, 2)
|
||||
}
|
||||
})
|
||||
SetSocketStatus(NODE.Socket, 1)
|
||||
NODE.Socket.Node = NODE
|
||||
NODE.Socket.ConnectID = "~C" + ConnectIDCount
|
||||
ConnectIDCount++
|
||||
this.SetEventsProcessing(NODE.Socket, 0)
|
||||
}
|
||||
CreateReconnection() {
|
||||
let NODE = this;
|
||||
global.AddNodeInfo(NODE, "===CreateReconnection===")
|
||||
global.CloseSocket(NODE.Socket2, "CreateReconnection")
|
||||
NODE.SocketStart = Date.now()
|
||||
NODE.Socket2 = net.createConnection(NODE.port, NODE.ip, function() {
|
||||
if (NODE.Socket2) {
|
||||
socketInit(NODE.Socket2, "s")
|
||||
global.AddNodeInfo(NODE, "OK Reconnected *" + NODE.Socket2.ConnectID)
|
||||
NODE.Socket2.ConnectToServer = true
|
||||
SetSocketStatus(NODE.Socket2, 2)
|
||||
}
|
||||
})
|
||||
SetSocketStatus(NODE.Socket2, 1)
|
||||
NODE.Socket2.Node = NODE
|
||||
NODE.Socket2.ConnectID = "~R" + ConnectIDCount
|
||||
ConnectIDCount++
|
||||
this.SetEventsProcessing(NODE.Socket2, 1)
|
||||
}
|
||||
SwapSockets() {
|
||||
if (!this.Socket2)
|
||||
return;
|
||||
var SocketOld = this.Socket;
|
||||
this.Socket = this.Socket2
|
||||
this.Socket2 = undefined
|
||||
this.Socket.Node = this
|
||||
SetSocketStatus(this.Socket, 100)
|
||||
this.Socket.Buf = SocketOld.Buf
|
||||
global.SERVER.LoadBufSocketList.remove(SocketOld)
|
||||
global.SERVER.LoadBufSocketList.insert(this.Socket)
|
||||
SocketOld.Buf = undefined
|
||||
SocketOld.WasClose = 1
|
||||
SocketOld.Node = undefined
|
||||
this.ErrCount = 0
|
||||
}
|
||||
SetEventsProcessing(Socket, Reconnection) {
|
||||
let SOCKET = Socket;
|
||||
let NODE = this;
|
||||
let RECONNECTION = Reconnection;
|
||||
SOCKET.on('data', function(data) {
|
||||
if (Socket.WasClose)
|
||||
return;
|
||||
if (GetSocketStatus(SOCKET) === 2) {
|
||||
SetSocketStatus(SOCKET, 3)
|
||||
var Buf = global.SERVER.GetDataFromBuf(data);
|
||||
if (Buf) {
|
||||
var Res = NODE.SendPOWFromClientToServer(SOCKET, Buf.Data);
|
||||
if (Res) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
global.CloseSocket(SOCKET, Buf ? "Method=" + Buf.Method : "=CLIENT ON DATA=")
|
||||
}
|
||||
else
|
||||
if (GetSocketStatus(SOCKET) === 3) {
|
||||
var Buf = global.SERVER.GetDataFromBuf(data);
|
||||
if (Buf) {
|
||||
var Str = Buf.Data;
|
||||
if (Str && Str.substr(0, 24) === "WAIT_CONNECT_FROM_SERVER") {
|
||||
global.AddNodeInfo(NODE, "2. CLIENT OK POW")
|
||||
global.CloseSocket(SOCKET, "WAIT_CONNECT_FROM_SERVER")
|
||||
NODE.WaitConnectFromServer = 1
|
||||
NODE.WaitConnectIP = NODE.ip
|
||||
try {
|
||||
NODE.SecretForReconnect = global.GetArrFromHex(Str.substr(25))
|
||||
}
|
||||
catch (e) {
|
||||
NODE.SecretForReconnect = []
|
||||
global.ToLog(e)
|
||||
}
|
||||
}
|
||||
else
|
||||
if (Str === "OK") {
|
||||
NODE.NextConnectDelta = 1000
|
||||
SetSocketStatus(SOCKET, 100)
|
||||
global.AddNodeInfo(NODE, "4. CLIENT OK CONNECT")
|
||||
if (RECONNECTION) {
|
||||
if (NODE.Socket)
|
||||
SetSocketStatus(NODE.Socket, 200)
|
||||
}
|
||||
else {
|
||||
if (!NODE.Active)
|
||||
global.SERVER.AddNodeToActive(NODE)
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
if (Str === "SELF") {
|
||||
NODE.Self = 1
|
||||
}
|
||||
else
|
||||
if (Str === "DOUBLE") {
|
||||
}
|
||||
else {
|
||||
global.AddNodeInfo(NODE, "ERROR:" + Str)
|
||||
}
|
||||
}
|
||||
global.CloseSocket(SOCKET, Buf ? "Method=" + Buf.Method + ":" + Str : "=CLIENT ON DATA=")
|
||||
}
|
||||
else {
|
||||
socketRead(Socket, data)
|
||||
global.SERVER.OnGetFromTCP(NODE, Socket, data)
|
||||
}
|
||||
})
|
||||
SOCKET.on('end', function() {
|
||||
if (GetSocketStatus(SOCKET))
|
||||
global.AddNodeInfo(NODE, "Get socket end *" + SOCKET.ConnectID + " Stat: " + SocketStatistic(SOCKET))
|
||||
if (GetSocketStatus(SOCKET) === 200) {
|
||||
NODE.SwapSockets()
|
||||
SOCKET.WasClose = 1
|
||||
}
|
||||
})
|
||||
SOCKET.on('close', function(err) {
|
||||
if (SOCKET.ConnectID && GetSocketStatus(SOCKET))
|
||||
global.AddNodeInfo(NODE, "Get socket close *" + SOCKET.ConnectID + " Stat: " + SocketStatistic(SOCKET))
|
||||
if (!SOCKET.WasClose) {
|
||||
if (GetSocketStatus(SOCKET) >= 2) {
|
||||
global.CloseSocket(SOCKET, "GET CLOSE")
|
||||
}
|
||||
}
|
||||
SetSocketStatus(SOCKET, 0)
|
||||
})
|
||||
SOCKET.on('error', function(err) {
|
||||
if (GetSocketStatus(SOCKET) >= 2) {
|
||||
global.SERVER.AddCheckErrCount(NODE, 1, "ERR##1 : socket")
|
||||
global.ADD_TO_STAT("ERRORS")
|
||||
}
|
||||
})
|
||||
}
|
||||
SendPOWFromClientToServer(Socket, data) {
|
||||
var Node = this;
|
||||
if (Node.ReconnectFromServer) {
|
||||
Node.ReconnectFromServer = 0
|
||||
var Info = this.GetPOWClientData(0);
|
||||
Info.Reconnect = 1
|
||||
Info.SecretForReconnect = Node.SecretForReconnect
|
||||
var BufWrite = global.BufLib.GetBufferFromObject(Info, FORMAT_POW_TO_SERVER, 1200, {});
|
||||
var BufAll = global.SERVER.GetBufFromData("POW_CONNECT7", BufWrite, 1);
|
||||
Socket.write(BufAll)
|
||||
return 1;
|
||||
}
|
||||
try {
|
||||
var Buf = global.BufLib.GetObjectFromBuffer(data, FORMAT_POW_TO_CLIENT, {});
|
||||
}
|
||||
catch (e) {
|
||||
global.SERVER.Sendglobal.CloseSocket(Socket, "FORMAT_POW_TO_CLIENT")
|
||||
return 0;
|
||||
}
|
||||
if (global.CompareArr(Buf.addrArr, global.SERVER.addrArr) === 0) {
|
||||
Node.Self = true
|
||||
global.AddNodeInfo(Node, "END: SELF")
|
||||
global.SERVER.Sendglobal.CloseSocket(Socket, "SELF")
|
||||
return;
|
||||
}
|
||||
var addrStr = GetHexFromAddres(Buf.addrArr);
|
||||
if (!Node.StartFindList && addrStr !== Node.addrStr) {
|
||||
global.AddNodeInfo(Node, "END: CHANGED ADDR: " + Node.addrStr.substr(0, 16) + "->" + addrStr.substr(0, 16))
|
||||
global.SERVER.Sendglobal.CloseSocket(Socket, "ADDRESS_HAS_BEEN_CHANGED")
|
||||
return;
|
||||
}
|
||||
if (Node.addrStrTemp) {
|
||||
global.AddNodeInfo(Node, "Set Addr = " + addrStr)
|
||||
Node.addrStr = addrStr
|
||||
global.SERVER.CheckNodeMap(Node)
|
||||
}
|
||||
var Result = false;
|
||||
if (Buf.PubKeyType === 2 || Buf.PubKeyType === 3) {
|
||||
Result = secp256k1.verify(Buffer.from(shaarr(addrStr)), Buffer.from(Buf.Sign), Buffer.from([Buf.PubKeyType].concat(Buf.addrArr)))
|
||||
if (!Result) {
|
||||
Result = secp256k1.verify(Buffer.from(sha3(addrStr)), Buffer.from(Buf.Sign), Buffer.from([Buf.PubKeyType].concat(Buf.addrArr)))
|
||||
}
|
||||
}
|
||||
if (!Result) {
|
||||
global.ToLog("END: ERROR_SIGN_SERVER ADDR: " + addrStr.substr(0, 16) + " from ip: " + Socket.remoteAddress)
|
||||
global.AddNodeInfo(Node, "END: ERROR_SIGN_SERVER ADDR: " + addrStr.substr(0, 16) + " from ip: " + Socket.remoteAddress)
|
||||
global.SERVER.Sendglobal.CloseSocket(Socket, "ERROR_SIGN_SERVER")
|
||||
return;
|
||||
}
|
||||
if (Buf.MIN_POWER_POW_HANDSHAKE > 1 + MIN_POWER_POW_HANDSHAKE) {
|
||||
global.ToLog("END: BIG_MIN_POWER_POW_HANDSHAKE ADDR: " + addrStr.substr(0, 16) + " from ip: " + Socket.remoteAddress)
|
||||
return 0;
|
||||
}
|
||||
var TestNode = global.SERVER.NodesMap[addrStr];
|
||||
if (TestNode && TestNode !== Node) {
|
||||
if (GetSocketStatus(TestNode.Socket)) {
|
||||
global.AddNodeInfo(Node, "DoubleConnection find")
|
||||
Node.DoubleConnection = true
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
global.AddNodeInfo(Node, "DoubleConnection find")
|
||||
TestNode.DoubleConnection = true
|
||||
}
|
||||
}
|
||||
Node.PubKey = Buffer.from([Buf.PubKeyType].concat(Buf.addrArr))
|
||||
Node.addrArr = Buf.addrArr
|
||||
Node.addrStr = addrStr
|
||||
if (global.CompareArr(SERVER.addrArr, Node.addrArr) === 0) {
|
||||
Node.Self = 1
|
||||
return 0;
|
||||
}
|
||||
var Hash = shaarr2(Buf.addrArr, Buf.HashRND);
|
||||
var nonce = CreateNoncePOWExternMinPower(Hash, 0, Buf.MIN_POWER_POW_HANDSHAKE);
|
||||
var Info;
|
||||
if (WALLET.WalletOpen && IsDeveloperAccount(WALLET.PubKeyArr)) {
|
||||
Info = this.GetPOWClientData(0)
|
||||
Info.Reconnect = 255
|
||||
Info.Sign = secp256k1.sign(SHA3BUF(Hash), WALLET.KeyPair.getPrivateKey('')).signature
|
||||
Result = CheckDevelopSign(Hash, Info.Sign)
|
||||
if (!Result) {
|
||||
throw "ERROR DEVELOPSIGN!";
|
||||
}
|
||||
}
|
||||
else {
|
||||
Info = this.GetPOWClientData(nonce)
|
||||
Info.PubKeyType = global.SERVER.PubKeyType
|
||||
Info.Sign = secp256k1.sign(Buffer.from(Hash), global.SERVER.KeyPair.getPrivateKey('')).signature
|
||||
}
|
||||
var BufWrite = global.BufLib.GetBufferFromObject(Info, FORMAT_POW_TO_SERVER, 1200, {});
|
||||
var BufAll = global.SERVER.GetBufFromData("POW_CONNECT6", BufWrite, 1);
|
||||
Socket.write(BufAll)
|
||||
return 1;
|
||||
}
|
||||
GetPOWClientData(nonce) {
|
||||
var Node = this;
|
||||
var Info = {};
|
||||
Info.DEF_NETWORK = GetNetworkName()
|
||||
Info.DEF_VERSION = DEF_VERSION
|
||||
Info.DEF_CLIENT = DEF_CLIENT
|
||||
Info.addrArr = global.SERVER.addrArr
|
||||
Info.ToIP = Node.ip
|
||||
Info.ToPort = Node.port
|
||||
Info.FromIP = global.SERVER.ip
|
||||
Info.FromPort = global.SERVER.port
|
||||
Info.nonce = nonce
|
||||
Info.Reconnect = 0
|
||||
Info.SendBytes = 0
|
||||
Info.SecretForReconnect = []
|
||||
Info.Reserv = []
|
||||
if (GrayConnect())
|
||||
Info.GrayConnect = 1
|
||||
return Info;
|
||||
}
|
||||
write(BufWrite) {
|
||||
if (!this.Socket)
|
||||
return;
|
||||
global.socketWrite(this.Socket, BufWrite)
|
||||
try {
|
||||
this.Socket.write(BufWrite)
|
||||
}
|
||||
catch (e) {
|
||||
global.ToError(e)
|
||||
this.Socket.WasClose = 1
|
||||
this.Socket.SocketStatus = 0
|
||||
this.Socket.Node = undefined
|
||||
}
|
||||
}
|
||||
};
|
||||
global.socketInit = function(Socket, Str) {
|
||||
if (!Socket)
|
||||
return;
|
||||
Socket.GetBytes = 0;
|
||||
Socket.SendBytes = 0;
|
||||
Socket.ConnectID = "" + ConnectIDCount + Str;
|
||||
ConnectIDCount++;
|
||||
};
|
||||
global.socketRead = function(Socket, Buf) {
|
||||
Socket.GetBytes += Buf.length;
|
||||
};
|
||||
global.socketWrite = function(Socket, Buf) {
|
||||
Socket.SendBytes += Buf.length;
|
||||
};
|
||||
global.CloseSocket = function(Socket, StrError?, bHide?) {
|
||||
if (!Socket || Socket.WasClose) {
|
||||
if (Socket)
|
||||
Socket.SocketStatus = 0;
|
||||
return;
|
||||
}
|
||||
var Node = Socket.Node;
|
||||
if (Socket.Node && Socket.Node.Socket2 === Socket && Socket.Node.Socket && Socket.Node.Socket.SocketStatus === 200)
|
||||
SetSocketStatus(Socket.Node.Socket, 100);
|
||||
var StrNode = NodeInfo(Socket.Node);
|
||||
Socket.WasClose = 1;
|
||||
Socket.SocketStatus = 0;
|
||||
Socket.Node = undefined;
|
||||
Socket.end();
|
||||
if (!bHide)
|
||||
global.AddNodeInfo(Node, "CLOSE " + StrNode + " *" + Socket.ConnectID + " - " + StrError);
|
||||
};
|
||||
|
||||
function SetSocketStatus(Socket, Status) {
|
||||
if (Socket && Socket.SocketStatus !== Status) {
|
||||
if (Status === 100 && (Socket.SocketStatus !== 3 && Socket.SocketStatus !== 200)) {
|
||||
ToLogTrace("===================ERROR=================== " + Status);
|
||||
return;
|
||||
}
|
||||
if (Status === 100 && Socket.Node)
|
||||
Socket.Node.LastTime = global.GetCurrentTime() - 0;
|
||||
Socket.SocketStatus = Status;
|
||||
Socket.TimeStatus = Date.now();
|
||||
}
|
||||
};
|
||||
|
||||
function GetSocketStatus(Socket) {
|
||||
if (Socket && Socket.SocketStatus) {
|
||||
if (Socket.SocketStatus !== 100) {
|
||||
var Delta = Date.now() - Socket.TimeStatus;
|
||||
if (Delta > MAX_WAIT_PERIOD_FOR_STATUS) {
|
||||
global.CloseSocket(Socket, "MAX_WAIT_PERIOD_FOR_STATUS = " + Socket.SocketStatus + " time = " + Delta);
|
||||
}
|
||||
}
|
||||
return Socket.SocketStatus;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
function SocketInfo(Socket) {
|
||||
if (Socket)
|
||||
return "*" + Socket.ConnectID;
|
||||
else
|
||||
return "";
|
||||
};
|
||||
|
||||
function SocketStatistic(Socket) {
|
||||
if (!Socket)
|
||||
return "";
|
||||
var Str = "";
|
||||
if (!Socket.SendBytes)
|
||||
Socket.SendBytes = 0;
|
||||
if (!Socket.GetBytes)
|
||||
Socket.GetBytes = 0;
|
||||
if (Socket.SendBytes)
|
||||
Str += " Send=" + Socket.SendBytes;
|
||||
if (Socket.GetBytes)
|
||||
Str += " Get=" + Socket.GetBytes;
|
||||
if (GetSocketStatus(Socket))
|
||||
Str += " SocketStatus=" + GetSocketStatus(Socket);
|
||||
if (Str === "")
|
||||
Str = "0";
|
||||
return Str;
|
||||
};
|
||||
|
||||
function NodeInfo(Node) {
|
||||
if (Node)
|
||||
return "" + Node.ip + ":" + Node.port + " " + SocketInfo(Node.Socket);
|
||||
else
|
||||
return "";
|
||||
};
|
||||
|
||||
function NodeName(Node) {
|
||||
if (!Node)
|
||||
return "";
|
||||
if (Node.Name)
|
||||
return Node.Name;
|
||||
if (LOCAL_RUN)
|
||||
return "" + Node.port;
|
||||
else {
|
||||
return "" + Node.ip + ":" + Node.addrStr.substr(0, 6);
|
||||
}
|
||||
};
|
||||
|
||||
function FindNodeByAddr(Addr, bConnect) {
|
||||
var Node = global.SERVER.NodesMap[Addr.trim()];
|
||||
if (Node && Node.ConnectStatus() === 100)
|
||||
return Node;
|
||||
if (Node && bConnect) {
|
||||
Node.NextConnectDelta = 1000;
|
||||
global.SERVER.StartConnectTry(Node);
|
||||
return false;
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
function AddNodeInfo(Node, Str, bSet) {
|
||||
if (!global.STAT_MODE)
|
||||
return;
|
||||
if (!Node)
|
||||
return;
|
||||
if (!Node.Info)
|
||||
Node.Info = "";
|
||||
if (bSet) {
|
||||
Node.Info = "";
|
||||
}
|
||||
else {
|
||||
if (Node.Socket && Node.Socket.Info) {
|
||||
Node.Info += Node.Socket.Info + "\n";
|
||||
Node.Socket.Info = "";
|
||||
}
|
||||
}
|
||||
if (Node.Info.length > 1000) {
|
||||
Node.PrevInfo = Node.Info;
|
||||
Node.Info = "";
|
||||
}
|
||||
{
|
||||
var timesend = GetStrOnlyTimeUTC();
|
||||
Str = timesend + " " + Str;
|
||||
Node.Info += Str + "\n";
|
||||
}
|
||||
};
|
||||
global.SocketStatistic = SocketStatistic;
|
||||
global.GetSocketStatus = GetSocketStatus;
|
||||
global.SetSocketStatus = SetSocketStatus;
|
||||
global.NodeInfo = NodeInfo;
|
||||
global.NodeName = NodeName;
|
||||
global.SocketInfo = SocketInfo;
|
||||
global.FindNodeByAddr = FindNodeByAddr;
|
||||
global.AddNodeInfo = AddNodeInfo;
|
||||
453
src/core/rest-loader.ts
Normal file
453
src/core/rest-loader.ts
Normal file
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* @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";
|
||||
module.exports = class CRest extends require("./db/block-db")
|
||||
{
|
||||
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
|
||||
super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
|
||||
}
|
||||
CheckSyncRest() {
|
||||
var BlockNumTime = GetCurrentBlockNumByTime();
|
||||
var Delta = BlockNumTime - this.BlockNumDB;
|
||||
if (Delta > REST_START_COUNT + DELTA_BLOCK_ACCOUNT_HASH + 500) {
|
||||
var BlockNumRest = GetCurrentRestNum(REST_START_COUNT + DELTA_BLOCK_ACCOUNT_HASH + 500);
|
||||
if (this.BlockNumDB >= this.BlockNumDBMin && this.BlockNumDB <= this.BlockNumDBMin + global.BLOCK_PROCESSING_LENGTH2) {
|
||||
}
|
||||
else
|
||||
if (BlockNumRest > this.BlockNumDB) {
|
||||
}
|
||||
else {
|
||||
this.LoadRestContext = undefined
|
||||
return;
|
||||
}
|
||||
this.LoadRestContext = {
|
||||
Mode: 0, BlockNum: BlockNumRest, BlockNumRest: BlockNumRest, WasDelta: Delta, BlockNumProof: BlockNumRest + DELTA_BLOCK_ACCOUNT_HASH,
|
||||
CountProof: COUNT_BLOCKS_FOR_LOAD, StartTimeHistory: Date.now(), MaxTimeOut: 600 * 1000, LoopSyncRest: 1, SendGetHeaderCount: 0,
|
||||
ReceiveHeaderCount: 0, ArrProof: [], MapSend: {}
|
||||
}
|
||||
for (var i = 0; i < this.NodesArr.length; i++) {
|
||||
this.NodesArr[i].SendRestGetHeader = 0
|
||||
}
|
||||
global.ToLog("**********START REST MODE: " + this.LoadRestContext.BlockNumProof)
|
||||
}
|
||||
else {
|
||||
this.LoadRestContext = undefined
|
||||
}
|
||||
}
|
||||
LoopSyncRest() {
|
||||
let Context = this.LoadRestContext;
|
||||
switch (Context.Mode) {
|
||||
case 0:
|
||||
var ArrNodes = this.GetActualNodes();
|
||||
for (var i = 0; i < ArrNodes.length; i++) {
|
||||
var Node = ArrNodes[i];
|
||||
if (!Node || Node.SendRestGetHeader) {
|
||||
continue;
|
||||
}
|
||||
Node.SendRestGetHeader = 1
|
||||
global.ToLog("Send rest get headers from " + Context.BlockNumProof + " to " + NodeName(Node), 2)
|
||||
this.SendF(Node, {
|
||||
"Method": "GETBLOCKHEADER", "Data": { Foward: 1, BlockNum: Context.BlockNumProof, Hash: [] }, "Context": { F: this.RETBLOCKHEADER_REST.bind(this) },
|
||||
})
|
||||
Context.SendGetHeaderCount++
|
||||
break;
|
||||
}
|
||||
if (Context.ReceiveHeaderCount >= COUNT_NODE_PROOF) {
|
||||
Context.Mode = 2
|
||||
global.ToLog("Next mode: " + Context.Mode + " Receive:" + Context.ReceiveHeaderCount + "/" + Context.SendGetHeaderCount, 2)
|
||||
}
|
||||
break;
|
||||
case 1000:
|
||||
break;
|
||||
case 2:
|
||||
var MapSumPower = {};
|
||||
for (var i = 0; i < Context.ArrProof.length; i++) {
|
||||
var Item = Context.ArrProof[i];
|
||||
if (!MapSumPower[Item.SumPower])
|
||||
MapSumPower[Item.SumPower] = 0
|
||||
MapSumPower[Item.SumPower]++
|
||||
}
|
||||
var MaxCount = 0, MaxPow = 0;
|
||||
for (var key in MapSumPower) {
|
||||
if (MapSumPower[key] >= MaxCount) {
|
||||
MaxCount = MapSumPower[key]
|
||||
MaxPow = parseInt(key)
|
||||
}
|
||||
}
|
||||
if (MaxCount < 2 || MaxPow === 0) {
|
||||
global.ToLog("****************************************************************** Error MaxPow - reload.")
|
||||
this.CheckSyncRest()
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < Context.ArrProof.length; i++) {
|
||||
var Item = Context.ArrProof[i];
|
||||
if (Item.SumPower !== MaxPow) {
|
||||
var Str = "BAD SumPower: " + Item.SumPower + "/" + MaxPow;
|
||||
global.ToLog(Str + " from: " + NodeName(Item.Node), 2)
|
||||
}
|
||||
else
|
||||
if (Item.SumPower && Item.arr.length >= Context.CountProof) {
|
||||
Item.OK = 1
|
||||
Context.BlockProof = Item.arr[0]
|
||||
}
|
||||
}
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode + " SumPower:" + MaxPow, 2)
|
||||
break;
|
||||
case 3:
|
||||
if (global.TX_PROCESS && global.TX_PROCESS.RunRPC) {
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
var Block = { BlockNum: Context.BlockNumRest };
|
||||
this.BlockNumDB = Block.BlockNum
|
||||
this.BlockNumDBMin = Block.BlockNum
|
||||
this.WriteBlockHeaderDB(Block)
|
||||
this.UseTruncateBlockDB = undefined
|
||||
global.TX_PROCESS.RunRPC("TXPrepareLoadRest", Block.BlockNum, function(Err, Params) {
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
})
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
break;
|
||||
case 5:
|
||||
let BlockProof = Context.BlockProof;
|
||||
var SendCount = 0;
|
||||
if (BlockProof)
|
||||
for (var i = 0; i < Context.ArrProof.length; i++) {
|
||||
let Item = Context.ArrProof[i];
|
||||
if (Item.OK) {
|
||||
SendCount++
|
||||
global.ToLog("Send rest get block proof:" + BlockProof.BlockNum + " to " + NodeName(Item.Node), 2)
|
||||
this.SendF(Item.Node, {
|
||||
"Method": "GETBLOCK", "Data": { BlockNum: BlockProof.BlockNum, TreeHash: BlockProof.TreeHash }, "Context": {
|
||||
F: function(Info) {
|
||||
if (Context.TxProof)
|
||||
return;
|
||||
var Data = global.BufLib.GetObjectFromBuffer(Info.Data, FORMAT_BLOCK_TRANSFER, WRK_BLOCK_TRANSFER);
|
||||
Info.Data = undefined
|
||||
if (Data.BlockNum !== BlockProof.BlockNum || global.CompareArr(Data.TreeHash, BlockProof.TreeHash) !== 0) {
|
||||
global.ToLog("Error get proof block from " + NodeName(Item.Node), 2)
|
||||
return;
|
||||
}
|
||||
var TreeHash = CalcTreeHashFromArrBody(Data.BlockNum, Data.arrContent);
|
||||
if (global.CompareArr(BlockProof.TreeHash, TreeHash) !== 0) {
|
||||
global.ToLog("Error TreeHash in proof block from " + NodeName(Item.Node), 2)
|
||||
return;
|
||||
}
|
||||
global.ToLog("GET BLOCK proof from " + NodeName(Item.Node), 2)
|
||||
var FindTx = undefined;
|
||||
for (var n = 0; n < Data.arrContent.length; n++) {
|
||||
var Body = Data.arrContent[n];
|
||||
if (Body[0] === TYPE_TRANSACTION_ACC_HASH) {
|
||||
try {
|
||||
FindTx = global.BufLib.GetObjectFromBuffer(Body, FORMAT_ACCOUNT_HASH3, {})
|
||||
}
|
||||
catch (e) {
|
||||
global.ToLog("Error parsing Body[" + n + "] block proof: " + e, 2)
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!FindTx)
|
||||
return;
|
||||
Context.TxProof = FindTx
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
Context.AccTaskList = []
|
||||
Context.AccTaskFinished = 0
|
||||
var AccCount = FindTx.AccountMax + 1;
|
||||
for (var n = 0; n < AccCount; n += MAX_ACCOUNTS_TRANSFER) {
|
||||
var Task = { StartNum: n, Count: MAX_ACCOUNTS_TRANSFER, Time: 0, MapSend: {} };
|
||||
if (Task.StartNum + Task.Count > AccCount)
|
||||
Task.Count = AccCount - Task.StartNum
|
||||
Context.AccTaskList.push(Task)
|
||||
}
|
||||
Context.SmartTaskList = []
|
||||
Context.SmartTaskFinished = 0
|
||||
for (var n = 0; n < FindTx.SmartCount; n += MAX_SMARTS_TRANSFER) {
|
||||
var Task = { StartNum: n, Count: MAX_SMARTS_TRANSFER, Time: 0, MapSend: {} };
|
||||
if (Task.StartNum + Task.Count > FindTx.SmartCount)
|
||||
Task.Count = FindTx.SmartCount - Task.StartNum
|
||||
Context.SmartTaskList.push(Task)
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
if (SendCount >= 5)
|
||||
break;
|
||||
}
|
||||
}
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
break;
|
||||
case 6:
|
||||
break;
|
||||
case 7:
|
||||
if (Context.AccTaskFinished === Context.AccTaskList.length) {
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
break;
|
||||
}
|
||||
var CurTime = Date.now();
|
||||
for (var i = 0; i < Context.AccTaskList.length; i++) {
|
||||
let Task = Context.AccTaskList[i];
|
||||
var Delta = CurTime - Task.Time;
|
||||
if (Delta > 5 * 1000 && !Task.OK) {
|
||||
var Ret = this.GetNextNode(Task, "", 1);
|
||||
if (Ret.Result) {
|
||||
global.ToLog("Send GETREST Num:" + Task.StartNum + "-" + Task.Count + " to " + NodeName(Ret.Node), 2)
|
||||
var SELF = this;
|
||||
this.SendF(Ret.Node, {
|
||||
"Method": "GETREST", "Data": { BlockNum: Context.BlockNumRest, AccNum: Task.StartNum, Count: Task.Count, AccHash: Context.TxProof.AccHash },
|
||||
"Context": {
|
||||
F: function(Info) {
|
||||
if (Task.OK)
|
||||
return;
|
||||
var Data = SELF.DataFromF(Info);
|
||||
if (!Data.Result)
|
||||
return;
|
||||
if (Data.Version !== 1) {
|
||||
global.ToLog("ERROR Version Result GETREST Num:" + Task.StartNum + " from " + NodeName(Info.Node), 2)
|
||||
return;
|
||||
}
|
||||
if (CompareArrL(Data.ProofHash, Context.TxProof.AccHash) !== 0) {
|
||||
global.ToLog("ERROR PROOF HASH Result GETREST Num:" + Task.StartNum + " Hash: " + global.GetHexFromArr(Data.ProofHash) + "/" + global.GetHexFromArr(Context.TxProof.AccHash) + " from " + NodeName(Info.Node),
|
||||
2)
|
||||
return;
|
||||
}
|
||||
var ArrM = [];
|
||||
for (var i = 0; i < Data.Arr.length; i++) {
|
||||
ArrM[i] = global.shaarr(Data.Arr[i])
|
||||
}
|
||||
var GetHash = CheckMerkleProof(Data.ProofArrL, ArrM, Data.ProofArrR);
|
||||
if (CompareArrL(GetHash, Context.TxProof.AccHash) !== 0) {
|
||||
global.ToLog("ERROR CALC PROOF HASH Result GETREST Num:" + Task.StartNum + " Hash: " + global.GetHexFromArr(GetHash) + "/" + global.GetHexFromArr(Context.TxProof.AccHash) + " from " + NodeName(Info.Node),
|
||||
2)
|
||||
return;
|
||||
}
|
||||
global.ToLog("OK Result GETREST Num:" + Task.StartNum + " arr=" + Data.Arr.length + " from " + NodeName(Info.Node), 2)
|
||||
if (!global.TX_PROCESS || !global.TX_PROCESS.RunRPC) {
|
||||
global.ToLog("ERROR global.TX_PROCESS")
|
||||
return;
|
||||
}
|
||||
Task.OK = 1
|
||||
global.TX_PROCESS.RunRPC("TXWriteAccArr", { StartNum: Task.StartNum, Arr: Data.Arr }, function(Err, Params) {
|
||||
Context.AccTaskFinished++
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
Task.Time = CurTime
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
if (Context.SmartTaskFinished === Context.SmartTaskList.length) {
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
break;
|
||||
}
|
||||
var CurTime = Date.now();
|
||||
for (var i = 0; i < Context.SmartTaskList.length; i++) {
|
||||
let Task = Context.SmartTaskList[i];
|
||||
var Delta = CurTime - Task.Time;
|
||||
if (Delta > 3 * 1000 && !Task.OK) {
|
||||
var Ret = this.GetNextNode(Task, "", 1);
|
||||
if (Ret.Result) {
|
||||
global.ToLog("Send GETSMART Num:" + Task.StartNum + "-" + Task.Count + " to " + NodeName(Ret.Node), 2)
|
||||
var SELF = this;
|
||||
this.SendF(Ret.Node, {
|
||||
"Method": "GETSMART", "Data": { BlockNum: Context.BlockNumRest, SmartNum: Task.StartNum, Count: Task.Count },
|
||||
"Context": {
|
||||
F: function(Info) {
|
||||
if (Task.OK)
|
||||
return;
|
||||
var Data = SELF.DataFromF(Info);
|
||||
if (!Data.Result)
|
||||
return;
|
||||
global.ToLog("Result GETSMART Num:" + Task.StartNum + " arr=" + Data.Arr.length + " from " + NodeName(Info.Node), 2)
|
||||
Task.Node = Info.Node
|
||||
if (!global.TX_PROCESS || !global.TX_PROCESS.RunRPC)
|
||||
return;
|
||||
Task.OK = 1
|
||||
global.TX_PROCESS.RunRPC("TXWriteSmartArr", { StartNum: Task.StartNum, Arr: Data.Arr }, function(Err, Params) {
|
||||
Context.SmartTaskFinished++
|
||||
})
|
||||
}
|
||||
},
|
||||
})
|
||||
Task.Time = CurTime
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if (!global.TX_PROCESS || !global.TX_PROCESS.RunRPC)
|
||||
return;
|
||||
var ErrSmartNum = CheckHashSmarts(Context.TxProof.SmartHash);
|
||||
if (ErrSmartNum > 0) {
|
||||
var Str = "Error hash in smart num: " + ErrSmartNum;
|
||||
global.ToLog(Str, 2)
|
||||
var t = Math.trunc(ErrSmartNum / MAX_SMARTS_TRANSFER);
|
||||
var Task = Context.SmartTaskList[t];
|
||||
if (!Task) {
|
||||
global.ToLog("error task number: " + t)
|
||||
Context.Mode = 100
|
||||
}
|
||||
else {
|
||||
Task.OK = 0
|
||||
Context.Mode--
|
||||
Context.SmartTaskFinished--
|
||||
this.AddToBan(Task.Node, Str)
|
||||
}
|
||||
break;
|
||||
}
|
||||
var SELF = this;
|
||||
global.TX_PROCESS.RunRPC("TXWriteAccHash", {}, function(Err, Params) {
|
||||
if (!Params)
|
||||
return;
|
||||
if (global.CompareArr(Context.TxProof.AccHash, Params.AccHash) === 0 && global.CompareArr(Context.TxProof.SmartHash, Params.SmartHash) === 0) {
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
}
|
||||
else {
|
||||
global.ToLog("ERROR RESTS LOAD:")
|
||||
global.ToLog("Must AccHash:" + global.GetHexFromArr(Context.TxProof.AccHash))
|
||||
global.ToLog("Must SmartHash:" + global.GetHexFromArr(Context.TxProof.SmartHash))
|
||||
global.ToLog("Write AccHash:" + global.GetHexFromArr(Params.AccHash))
|
||||
global.ToLog("Write SmartHash:" + global.GetHexFromArr(Params.SmartHash))
|
||||
SELF.BlockNumDB = 0
|
||||
SELF.BlockNumDBMin = 0
|
||||
SELF.UseTruncateBlockDB = undefined
|
||||
global.TX_PROCESS.RunRPC("TXPrepareLoadRest", 0, function(Err, Params) {
|
||||
})
|
||||
Context.Mode = 100
|
||||
}
|
||||
})
|
||||
Context.Mode++
|
||||
global.ToLog("Next mode: " + Context.Mode, 2)
|
||||
break;
|
||||
case 10:
|
||||
break;
|
||||
case 11:
|
||||
var Context2 = this.LoadHistoryContext;
|
||||
Context2.BlockNum = this.LoadRestContext.BlockNumRest
|
||||
Context2.StartTimeHistory = Date.now()
|
||||
Context.Mode = 200
|
||||
break;
|
||||
case 200:
|
||||
global.ToLog("Error state!")
|
||||
break;
|
||||
}
|
||||
}
|
||||
RETBLOCKHEADER_REST(Info, CurTime) {
|
||||
if (Info.Node.SendRestGetHeader === 2)
|
||||
return;
|
||||
Info.Node.SendRestGetHeader = 2
|
||||
var Context = this.LoadRestContext;
|
||||
var BufRead = global.BufLib.GetReadBuffer(Info.Data);
|
||||
var arr = this.GetBlockArrFromBuffer_Load(BufRead, Info);
|
||||
global.ToLog("RETBLOCKHEADER_FOWARD SyncRest from " + NodeName(Info.Node) + " arr=" + arr.length, 2)
|
||||
Context.ReceiveHeaderCount++
|
||||
var MinSumPow = 10 * Context.CountProof;
|
||||
var SumPower = 0;
|
||||
if (arr.length >= Context.CountProof)
|
||||
for (var i = 0; i < Context.CountProof; i++) {
|
||||
SumPower += arr[i].Power
|
||||
}
|
||||
if (SumPower <= MinSumPow)
|
||||
SumPower = 0
|
||||
Context.ArrProof.push({ Node: Info.Node, SumPower: SumPower, arr: arr, BufRead: BufRead })
|
||||
}
|
||||
static
|
||||
GETSMART_F() {
|
||||
return "{\
|
||||
SmartNum:uint,\
|
||||
Count:uint,\
|
||||
}";
|
||||
}
|
||||
static
|
||||
RETSMART_F() {
|
||||
return global.FORMAT_SMART_TRANSFER;
|
||||
}
|
||||
static
|
||||
GETREST_F() {
|
||||
return "{\
|
||||
BlockNum:uint,\
|
||||
AccNum:uint,\
|
||||
Count:uint,\
|
||||
AccHash:hash,\
|
||||
}";
|
||||
}
|
||||
static
|
||||
RETREST_F() {
|
||||
return global.FORMAT_REST_TRANSFER;
|
||||
}
|
||||
SendLoadToBegin() {
|
||||
return;
|
||||
if (!this.BlockNumDBMin)
|
||||
return;
|
||||
if (!this.ContextSendLoadToBegin)
|
||||
this.ContextSendLoadToBegin = { Time: 0, MapSend: {} }
|
||||
var Context = this.ContextSendLoadToBegin;
|
||||
var CurTime = Date.now();
|
||||
var Delta = CurTime - Context.Time;
|
||||
if (Delta < 2 * 1000)
|
||||
return;
|
||||
var BlockDB = this.ReadBlockHeaderDB(this.BlockNumDBMin + 1);
|
||||
if (!BlockDB)
|
||||
return;
|
||||
Context.BlockNum = BlockDB.BlockNum
|
||||
var Ret = this.GetNextNode(Context, Context.BlockNum, 1);
|
||||
if (Ret.Result) {
|
||||
var Node = Ret.Node;
|
||||
global.ToLog("LOAD_TO_BEGIN - from: " + BlockDB.BlockNum + " to " + NodeName(Node), 2)
|
||||
Context.Time = CurTime
|
||||
this.SendF(Node, {
|
||||
"Method": "GETBLOCKHEADER", "Data": { Foward: 0, BlockNum: Context.BlockNum, Hash: BlockDB.Hash, IsSum: 0, Count: global.COUNT_HISTORY_BLOCKS_FOR_LOAD },
|
||||
"Context": {
|
||||
F: function(Info) {
|
||||
global.ToLog("GET LOAD_TO_BEGIN from " + NodeName(Info.Node) + " Length=" + Info.Data.length, 2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function CheckHashSmarts(LastSumHash) {
|
||||
global.DApps.Smart.Close();
|
||||
var MaxNum = global.DApps.Smart.GetMaxNum();
|
||||
var Item = global.DApps.Smart.DBSmart.Read(MaxNum);
|
||||
if (global.CompareArr(Item.SumHash, LastSumHash) !== 0)
|
||||
return MaxNum;
|
||||
var WorkStruct = {};
|
||||
for (var Num = MaxNum; Num >= 1; Num--) {
|
||||
var PrevItem = global.DApps.Smart.DBSmart.Read(Num - 1);
|
||||
if (!PrevItem)
|
||||
return Num;
|
||||
var WasSumHash = Item.SumHash;
|
||||
Item.SumHash = [];
|
||||
var Buf = global.BufLib.GetBufferFromObject(Item, global.DApps.Smart.FORMAT_ROW, 20000, WorkStruct);
|
||||
var Hash = global.sha3(Buf);
|
||||
var SumHash = sha3arr2(PrevItem.SumHash, Hash);
|
||||
if (global.CompareArr(SumHash, WasSumHash) !== 0)
|
||||
return Num;
|
||||
Item = PrevItem;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
73
src/core/rest_tables.ts
Normal file
73
src/core/rest_tables.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
|
||||
function DoRest(r,t,e)
|
||||
{
|
||||
var u = r.Arr[0], o = Math.floor(e / REST_BLOCK_SCALE);
|
||||
if(o !== Math.floor((u.BlockNum - 1) / REST_BLOCK_SCALE))
|
||||
{
|
||||
for(var n = GetRestArr(o), l = [], a = n.length - 2; 0 <= a; a--)
|
||||
l.push(n[a] * REST_BLOCK_SCALE);
|
||||
RestPush(r, l, e, 1);
|
||||
}
|
||||
r.Arr[0] = {BlockNum:e, Value:t.Value};
|
||||
};
|
||||
|
||||
function RestPush(r,t,e,u)
|
||||
{
|
||||
var o = r.Arr[u - 1], n = r.Arr[u];
|
||||
if(1 < u)
|
||||
{
|
||||
var l = t[u - 2];
|
||||
if(o.BlockNum > l)
|
||||
return ;
|
||||
}
|
||||
if(n.BlockNum && n.BlockNum >= e || o.BlockNum >= e)
|
||||
return n.BlockNum = 0, void (n.Value = {});
|
||||
n.BlockNum && u < r.Arr.length - 1 && RestPush(r, t, e, u + 1), r.Arr[u] = o;
|
||||
};
|
||||
|
||||
function GetRestArr(r)
|
||||
{
|
||||
for(var t = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0], e = t.length, u = 0; u <= r; u++)
|
||||
for(var o = 0, n = u, l = e - 1; 0 <= l; l--)
|
||||
{
|
||||
var a = t[l];
|
||||
if(t[l] = n, n = a, 0 == ((o = o << 4 | 15) & u))
|
||||
break;
|
||||
if(0 != (o & n))
|
||||
break;
|
||||
}
|
||||
return t;
|
||||
};
|
||||
var RestArrMap = {};
|
||||
|
||||
function GetCurrentRestArr()
|
||||
{
|
||||
var r = GetCurrentBlockNumByTime(), t = Math.floor(r / REST_BLOCK_SCALE), e = RestArrMap[t];
|
||||
if(void 0 === e)
|
||||
{
|
||||
RestArrMap = {}, (e = GetRestArr(t)).length = e.length - 1;
|
||||
for(var u = 0; u < e.length; u++)
|
||||
e[u] = e[u] * REST_BLOCK_SCALE;
|
||||
RestArrMap[t] = e;
|
||||
}
|
||||
return e;
|
||||
};
|
||||
|
||||
function GetCurrentRestNum(r)
|
||||
{
|
||||
for(var t = GetCurrentBlockNumByTime() - r, e = GetCurrentRestArr(), u = e.length - 1; 0 <= u; u--)
|
||||
if(e[u] <= t)
|
||||
return e[u];
|
||||
return 0;
|
||||
};
|
||||
global.DoRest = DoRest, global.GetRestArr = GetRestArr, global.GetCurrentRestArr = GetCurrentRestArr, global.GetCurrentRestNum = GetCurrentRestNum;
|
||||
1061
src/core/server.ts
Normal file
1061
src/core/server.ts
Normal file
File diff suppressed because it is too large
Load Diff
46
src/core/startlib.ts
Normal file
46
src/core/startlib.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* @project: TERA
|
||||
* @version: Development (beta)
|
||||
* @license: MIT (not for evil)
|
||||
* @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
|
||||
* Web: https://terafoundation.org
|
||||
* Twitter: https://twitter.com/terafoundation
|
||||
* Telegram: https://t.me/terafoundation
|
||||
*/
|
||||
|
||||
import * as fs from 'fs'
|
||||
|
||||
function CopyFiles(l, o, t) {
|
||||
if (fs.existsSync(l))
|
||||
for (var e = fs.readdirSync(l), n = 0; n < e.length; n++) {
|
||||
var a = l + "/" + e[n], s = o + "/" + e[n];
|
||||
if (fs.statSync(a).isDirectory())
|
||||
t && (fs.existsSync(s) || fs.mkdirSync(s), CopyFiles(a, s, t));
|
||||
else {
|
||||
var r = fs.readFileSync(a), i = fs.openSync(s, "w");
|
||||
fs.writeSync(i, r, 0, r.length), fs.closeSync(i);
|
||||
}
|
||||
}
|
||||
};
|
||||
global.GetDataPath = function(l) {
|
||||
return "/" !== global.DATA_PATH.substr(global.DATA_PATH.length - 1, 1) && (global.DATA_PATH = global.DATA_PATH + "/"), global.GetNormalPathString(global.DATA_PATH + l);
|
||||
}
|
||||
global.GetCodePath = function(l) {
|
||||
return "/" !== global.CODE_PATH.substr(global.CODE_PATH.length - 1, 1) && (global.CODE_PATH = global.CODE_PATH + "/"), global.GetNormalPathString(global.CODE_PATH + l);
|
||||
}
|
||||
global.GetNormalPathString = function(l: string) {
|
||||
return l.split("\\").join("/");
|
||||
}
|
||||
global.CheckCreateDir = function(l, o, t) {
|
||||
if (l = global.GetNormalPathString(l), !fs.existsSync(l)) {
|
||||
o || console.log("Create: " + l);
|
||||
var e = l.split("/"), n = e[0];
|
||||
t && e.length--;
|
||||
for (var a = 1; a < e.length; a++)
|
||||
n += "/" + e[a], fs.existsSync(n) || fs.mkdirSync(n);
|
||||
}
|
||||
}
|
||||
global.CopyFiles = CopyFiles
|
||||
global.ToLog || (global.ToLog = function(l) {
|
||||
console.log(l);
|
||||
});
|
||||
202
src/core/terahashmining.ts
Normal file
202
src/core/terahashmining.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
var START_NONCE = 0;
|
||||
const COUNT_FIND_HASH1 = 64;
|
||||
const DELTA_LONG_MINING = 5000;
|
||||
var BLOCKNUM_ALGO2 = 6560000;
|
||||
if (global.LOCAL_RUN || global.TEST_NETWORK) {
|
||||
BLOCKNUM_ALGO2 = 0;
|
||||
}
|
||||
require('./library.js');
|
||||
require('./crypto-library.js');
|
||||
require('../HTML/JS/terahashlib.js');
|
||||
var DELTA_NONCE = Math.pow(2, 40) * global.MINING_VERSION_NUM;
|
||||
global.CreateHashMinimal = CreateHashMinimal;
|
||||
global.CreatePOWVersionX = CreatePOWVersion3;
|
||||
|
||||
function CreateHashMinimal(Block, MinerID) {
|
||||
if (Block.BlockNum < BLOCKNUM_ALGO2) {
|
||||
throw "BlockNum < BLOCKNUM_ALGO2";
|
||||
return false;
|
||||
}
|
||||
var PrevHashNum = ReadUint32FromArr(Block.PrevHash, 28);
|
||||
var Ret = GetHash(Block.SeqHash, PrevHashNum, Block.BlockNum, MinerID, 0, 0, 0, 0, 0);
|
||||
Block.Hash = Ret.Hash;
|
||||
Block.PowHash = Ret.PowHash;
|
||||
Block.Power = GetPowPower(Block.PowHash);
|
||||
Block.AddrHash = [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];
|
||||
WriteUintToArrOnPos(Block.AddrHash, MinerID, 0);
|
||||
WriteUint32ToArrOnPos(Block.AddrHash, PrevHashNum, 28);
|
||||
return true;
|
||||
};
|
||||
var MAX_MEMORY3 = 0, SHIFT_MASKA3;
|
||||
var BufferNonce3, BufferBlockNum3;
|
||||
var bWasInitVer3, bWasInitVerOK3;
|
||||
|
||||
function InitVer3(Block) {
|
||||
bWasInitVer3 = 1;
|
||||
if (Block.ProcessMemorySize > 0) {
|
||||
var MAXARRAYSIZE = (1 << 30) * 2 - 1;
|
||||
var MaxArrCount = Math.min(Math.trunc(Block.ProcessMemorySize / 8), MAXARRAYSIZE);
|
||||
var BitCount = 0;
|
||||
MAX_MEMORY3 = 1;
|
||||
for (var b = 0; b < 32; b++) {
|
||||
if (MAX_MEMORY3 > MaxArrCount) {
|
||||
BitCount--;
|
||||
MAX_MEMORY3 = MAX_MEMORY3 / 2;
|
||||
break;
|
||||
}
|
||||
BitCount++;
|
||||
MAX_MEMORY3 = MAX_MEMORY3 * 2;
|
||||
}
|
||||
SHIFT_MASKA3 = 32 - BitCount;
|
||||
try {
|
||||
BufferNonce3 = new Uint32Array(MAX_MEMORY3);
|
||||
BufferBlockNum3 = new Uint32Array(MAX_MEMORY3);
|
||||
}
|
||||
catch (e) {
|
||||
SHIFT_MASKA3 = SHIFT_MASKA3 + 1;
|
||||
MAX_MEMORY3 = MAX_MEMORY3 / 2;
|
||||
global.ToLog("WAS ALLOC MEMORY ERROR. NEW TRY: " + MAX_MEMORY3);
|
||||
BufferNonce3 = new Uint32Array(MAX_MEMORY3);
|
||||
BufferBlockNum3 = new Uint32Array(MAX_MEMORY3);
|
||||
}
|
||||
bWasInitVerOK3 = 1;
|
||||
global.ToLog("MAX HASH ITEMS=" + Math.trunc(MAX_MEMORY3 / 1024 / 1024) + " M");
|
||||
}
|
||||
};
|
||||
|
||||
function CreatePOWVersion3(Block, bHashPump) {
|
||||
if (!bWasInitVer3)
|
||||
InitVer3(Block);
|
||||
if (!bWasInitVerOK3)
|
||||
return 0;
|
||||
if (!Block.LastNonce)
|
||||
Block.LastNonce = 0;
|
||||
if (!Block.HashCount)
|
||||
Block.HashCount = 0;
|
||||
if (!Block.LastNonce0)
|
||||
Block.LastNonce0 = 0;
|
||||
if (!Block.MaxLider) {
|
||||
Block.HashCount = 0;
|
||||
Block.MaxLider = {
|
||||
Nonce0: 0, Nonce1: 0, Nonce2: 0, DeltaNum1: 0, DeltaNum2: 0, Hash1: [255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255], Hash2: [255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255],
|
||||
};
|
||||
}
|
||||
var MaxLider = Block.MaxLider;
|
||||
var RunCount = Block.RunCount;
|
||||
var BlockNum = Block.BlockNum;
|
||||
var Miner = Block.MinerID;
|
||||
var StartNonceRnd = DELTA_NONCE + Block.LastNonce + Math.trunc(3000000000 * Math.random());
|
||||
var List = GetNonceHashArr(BlockNum, Miner, StartNonceRnd, RunCount);
|
||||
for (var n = 0; n < RunCount; n++) {
|
||||
var Nonce = List.ArrNonce[n];
|
||||
var HashNum = List.ArrHash[n] >>> SHIFT_MASKA3;
|
||||
BufferNonce3[HashNum] = Nonce;
|
||||
BufferBlockNum3[HashNum] = BlockNum;
|
||||
}
|
||||
Block.LastNonce += RunCount;
|
||||
if (bHashPump)
|
||||
return;
|
||||
var Ret = 0;
|
||||
var PrevHashNum = ReadUint32FromArr(Block.PrevHash, 28);
|
||||
var HashBase = GetHashFromNum2(BlockNum, PrevHashNum);
|
||||
var Value1 = FindHashBuffer3(HashBase, BlockNum, Miner, 1);
|
||||
if (Value1) {
|
||||
var Hash1 = XORArr(HashBase, Value1.Hash);
|
||||
if (global.CompareArr(MaxLider.Hash1, Hash1) > 0) {
|
||||
MaxLider.Hash1 = Hash1;
|
||||
MaxLider.Nonce1 = Value1.Nonce;
|
||||
MaxLider.DeltaNum1 = Value1.DeltaNum;
|
||||
Ret = 1;
|
||||
}
|
||||
}
|
||||
START_NONCE = Block.LastNonce0;
|
||||
var CountEnd = START_NONCE + 50000;
|
||||
var Nonce0;
|
||||
for (Nonce0 = START_NONCE; Nonce0 < CountEnd; Nonce0++) {
|
||||
var HashCurrent = GetHashFromArrNum2(Block.SeqHash, Miner, Nonce0);
|
||||
var Value2 = FindHashBuffer3(HashCurrent, BlockNum, Miner, 1);
|
||||
if (Value2) {
|
||||
var Hash2 = XORArr(HashCurrent, Value2.Hash);
|
||||
if (global.CompareArr(MaxLider.Hash2, Hash2) > 0) {
|
||||
MaxLider.Nonce0 = Nonce0;
|
||||
MaxLider.Hash2 = Hash2;
|
||||
MaxLider.Nonce2 = Value2.Nonce;
|
||||
MaxLider.DeltaNum2 = Value2.DeltaNum;
|
||||
Ret = 1;
|
||||
if (global.CompareArr(MaxLider.Hash1, Hash2) > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Block.LastNonce0 = Nonce0;
|
||||
if (Ret) {
|
||||
Block.AddrHash = [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];
|
||||
WriteUintToArrOnPos(Block.AddrHash, Miner, 0);
|
||||
WriteUintToArrOnPos(Block.AddrHash, MaxLider.Nonce0, 6);
|
||||
WriteUintToArrOnPos(Block.AddrHash, MaxLider.Nonce1, 12);
|
||||
WriteUintToArrOnPos(Block.AddrHash, MaxLider.Nonce2, 18);
|
||||
WriteUint16ToArrOnPos(Block.AddrHash, MaxLider.DeltaNum1, 24);
|
||||
WriteUint16ToArrOnPos(Block.AddrHash, MaxLider.DeltaNum2, 26);
|
||||
WriteUint32ToArrOnPos(Block.AddrHash, PrevHashNum, 28);
|
||||
Block.Hash = MaxLider.Hash2;
|
||||
if (global.CompareArr(MaxLider.Hash1, MaxLider.Hash2) > 0) {
|
||||
Block.PowHash = MaxLider.Hash1;
|
||||
}
|
||||
else {
|
||||
Block.PowHash = MaxLider.Hash2;
|
||||
}
|
||||
if (BlockNum >= global.BLOCKNUM_TICKET_ALGO)
|
||||
Block.Hash = sha3arr2(MaxLider.Hash1, MaxLider.Hash2);
|
||||
else
|
||||
Block.Hash = shaarr2(MaxLider.Hash1, MaxLider.Hash2);
|
||||
var Power = GetPowPower(Block.PowHash);
|
||||
Block.HashCount = (1 << Power) >>> 0;
|
||||
}
|
||||
return Ret;
|
||||
};
|
||||
|
||||
function FindHashBuffer3(HashFind, BlockNum, Miner, CountFind) {
|
||||
var HashNum = ReadIndexFromArr(HashFind);
|
||||
for (var i = 0; i < CountFind; i++) {
|
||||
var Index = HashNum ^ i;
|
||||
var BlockNum2 = BufferBlockNum3[Index];
|
||||
if (BlockNum2 && BlockNum2 > BlockNum - DELTA_LONG_MINING) {
|
||||
var Nonce2 = DELTA_NONCE + BufferNonce3[Index];
|
||||
var Hash2 = GetHashFromNum3(BlockNum2, Miner, Nonce2);
|
||||
return { Hash: Hash2, DeltaNum: BlockNum - BlockNum2, Nonce: Nonce2 };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
function ReadIndexFromArr(arr) {
|
||||
var value = (arr[0] << 23) * 2 + (arr[1] << 16) + (arr[2] << 8) + arr[3];
|
||||
value = value >>> SHIFT_MASKA3;
|
||||
return value;
|
||||
};
|
||||
global.GetNonceHashArr = function(BlockNum, Miner, StartNonceRnd, CountNonce) {
|
||||
var ArrNonce = [];
|
||||
var ArrHash = [];
|
||||
for (var n = 0; n < CountNonce; n++) {
|
||||
var Nonce = StartNonceRnd + n;
|
||||
var HashNonce = GetHashFromNum3(BlockNum, Miner, Nonce);
|
||||
var HashNum = (HashNonce[0] << 23) * 2 + (HashNonce[1] << 16) + (HashNonce[2] << 8) + HashNonce[3];
|
||||
ArrNonce[n] = Nonce;
|
||||
ArrHash[n] = HashNum;
|
||||
}
|
||||
return { ArrNonce: ArrNonce, ArrHash: ArrHash };
|
||||
};
|
||||
220
src/core/transaction-validator.ts
Normal file
220
src/core/transaction-validator.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* @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";
|
||||
require("../system/dapp");
|
||||
require("../system/accounts");
|
||||
require("../system/smart");
|
||||
require("../system/file");
|
||||
require("../system/messager");
|
||||
require("../system/names");
|
||||
if (global.PROCESS_NAME === "MAIN" || global.PROCESS_NAME === "TX")
|
||||
require("./wallet");
|
||||
module.exports = class CSmartContract extends require("./block-exchange")
|
||||
{
|
||||
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
|
||||
super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
|
||||
this.BufHashTree = new RBTree(CompareArr)
|
||||
this.BufHashTree.LastAddNum = 0
|
||||
}
|
||||
AddBlockToHashTree(Block) {
|
||||
this.BufHashTree.LastAddNum = Block.BlockNum
|
||||
var arr = Block.arrContent;
|
||||
if (arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var HASH = global.shaarr(arr[i]);
|
||||
this.BufHashTree.insert(HASH)
|
||||
}
|
||||
}
|
||||
}
|
||||
DeleteBlockFromHashTree(Block) {
|
||||
var arr = Block.arrContent;
|
||||
if (arr) {
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var HASH = global.shaarr(arr[i]);
|
||||
this.BufHashTree.remove(HASH)
|
||||
}
|
||||
}
|
||||
}
|
||||
OnWriteBlock(Block) {
|
||||
}
|
||||
BlockProcessTX(Block) {
|
||||
if (Block.BlockNum < 1)
|
||||
return;
|
||||
var COUNT_MEM_BLOCKS = 0;
|
||||
var NUM1 = 1240000;
|
||||
var NUM2 = 1400000;
|
||||
if (global.LOCAL_RUN) {
|
||||
NUM1 = 15
|
||||
NUM2 = 100
|
||||
}
|
||||
if (Block.BlockNum > global.BLOCKNUM_TICKET_ALGO) {
|
||||
NUM1 = 1000000000000
|
||||
NUM2 = 1000000000000
|
||||
}
|
||||
if (Block.BlockNum > NUM1) {
|
||||
COUNT_MEM_BLOCKS = 1
|
||||
if (Block.BlockNum > NUM2)
|
||||
COUNT_MEM_BLOCKS = 60
|
||||
if (this.BufHashTree.LastAddNum !== Block.BlockNum - 1) {
|
||||
this.BufHashTree.clear()
|
||||
for (var num = COUNT_MEM_BLOCKS; num >= 1; num--) {
|
||||
var Block2 = this.ReadBlockDB(Block.BlockNum - num);
|
||||
if (Block2) {
|
||||
this.AddBlockToHashTree(Block2)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var key in DApps) {
|
||||
DApps[key].OnWriteBlockStart(Block)
|
||||
}
|
||||
var arrContentResult = [];
|
||||
var BlockNum = Block.BlockNum;
|
||||
var arr = Block.arrContent;
|
||||
if (arr)
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var HASH = global.shaarr(arr[i]);
|
||||
if (this.BufHashTree.find(HASH)) {
|
||||
continue;
|
||||
}
|
||||
var type = arr[i][0];
|
||||
var App = DAppByType[type];
|
||||
if (App) {
|
||||
App.ResultTx = 0
|
||||
global.DApps.Accounts.BeginTransaction()
|
||||
var StrHex = global.GetHexFromArr(sha3(arr[i]));
|
||||
var item;
|
||||
global.CurTrItem = undefined
|
||||
if (global.TreeFindTX) {
|
||||
item = global.TreeFindTX.LoadValue(StrHex)
|
||||
if (item)
|
||||
global.CurTrItem = item.TX
|
||||
}
|
||||
var Result = App.OnWriteTransaction(Block, arr[i], BlockNum, i);
|
||||
var SetResult = Result;
|
||||
if (Result === true) {
|
||||
if (App.ResultTx)
|
||||
SetResult = App.ResultTx
|
||||
if (!DApps.Accounts.CommitTransaction(BlockNum, i))
|
||||
SetResult = 0
|
||||
}
|
||||
else {
|
||||
global.DApps.Accounts.RollBackTransaction()
|
||||
SetResult = 0
|
||||
}
|
||||
if (SetResult === true)
|
||||
SetResult = 1
|
||||
arrContentResult[i] = SetResult
|
||||
if (item) {
|
||||
var ResultStr = Result;
|
||||
if (Result === true || typeof Result === "number") {
|
||||
ResultStr = "Add to blockchain"
|
||||
if (type === global.TYPE_TRANSACTION_FILE)
|
||||
ResultStr += ": file/" + BlockNum + "/" + i
|
||||
}
|
||||
item.cmd = "RetFindTX"
|
||||
item.ResultStr = "" + ResultStr
|
||||
item.bFinal = 1
|
||||
item.Result = SetResult
|
||||
process.send(item)
|
||||
}
|
||||
global.CurTrItem = undefined
|
||||
}
|
||||
}
|
||||
if (COUNT_MEM_BLOCKS) {
|
||||
var Block2 = this.ReadBlockDB(Block.BlockNum - COUNT_MEM_BLOCKS);
|
||||
if (Block2)
|
||||
this.DeleteBlockFromHashTree(Block2)
|
||||
this.AddBlockToHashTree(Block)
|
||||
}
|
||||
if (arrContentResult.length)
|
||||
process.send({ cmd: "WriteBodyResult", BlockNum: Block.BlockNum, arrContentResult: arrContentResult })
|
||||
for (var key in DApps) {
|
||||
DApps[key].OnWriteBlockFinish(Block)
|
||||
}
|
||||
}
|
||||
BlockDeleteTX(Block) {
|
||||
this.BufHashTree.LastAddNum = 0
|
||||
for (var key in DApps) {
|
||||
DApps[key].OnDeleteBlock(Block)
|
||||
}
|
||||
}
|
||||
OnDelete(Block) {
|
||||
}
|
||||
IsValidTicket(Tr, BlockNum) {
|
||||
this.CheckCreateTicketObject(Tr, BlockNum)
|
||||
if (Tr.power < MIN_POWER_POW_TR)
|
||||
return - 2;
|
||||
if (Tr.num !== BlockNum)
|
||||
return - 3;
|
||||
return 1;
|
||||
}
|
||||
IsValidTransaction(Tr, BlockNum) {
|
||||
if (!Tr.body || Tr.body.length < MIN_TRANSACTION_SIZE || Tr.body.length > MAX_TRANSACTION_SIZE)
|
||||
return - 1;
|
||||
this.CheckCreateTransactionObject(Tr)
|
||||
if (Tr.power - Math.log2(Tr.body.length / 128) < MIN_POWER_POW_TR)
|
||||
return - 2;
|
||||
if (Tr.num !== BlockNum)
|
||||
return - 3;
|
||||
if (Tr.body[0] === TYPE_TRANSACTION_ACC_HASH)
|
||||
return - 4;
|
||||
return 1;
|
||||
}
|
||||
ReWriteDAppTransactions(Length) {
|
||||
if (!TX_PROCESS.Worker)
|
||||
return 0;
|
||||
if (!Length)
|
||||
return 0;
|
||||
var StartNum = this.BlockNumDB - Length + 1;
|
||||
if (StartNum < 0)
|
||||
StartNum = 0
|
||||
var EndNum = this.BlockNumDB;
|
||||
var MinBlock = global.DApps.Accounts.GetMinBlockAct();
|
||||
if (MinBlock > StartNum) {
|
||||
global.ToLog("Cant rewrite transactions. Very long length of the rewriting chain. Max length=" + (this.BlockNumDB - MinBlock))
|
||||
return 0;
|
||||
}
|
||||
if (global.TX_PROCESS && global.TX_PROCESS.RunRPC)
|
||||
global.TX_PROCESS.RunRPC("ReWriteDAppTransactions", { StartNum: StartNum, EndNum: EndNum })
|
||||
return 1;
|
||||
}
|
||||
AddDAppTransactions(BlockNum, Arr) {
|
||||
if (BlockNum % PERIOD_ACCOUNT_HASH !== 0)
|
||||
return;
|
||||
var BlockNumHash = BlockNum - DELTA_BLOCK_ACCOUNT_HASH;
|
||||
if (BlockNumHash < 0)
|
||||
return;
|
||||
var Item = global.DApps.Accounts.GetAccountHashItem(BlockNumHash);
|
||||
if (Item) {
|
||||
var Body = [TYPE_TRANSACTION_ACC_HASH];
|
||||
WriteUintToArr(Body, BlockNumHash)
|
||||
WriteArrToArr(Body, Item.AccHash, 32)
|
||||
if (BlockNumHash >= START_BLOCK_ACCOUNT_HASH3) {
|
||||
WriteUintToArr(Body, Item.AccountMax)
|
||||
WriteArrToArr(Body, Item.SmartHash, 32)
|
||||
WriteUintToArr(Body, Item.SmartCount)
|
||||
WriteUintToArr(Body, BlockNum)
|
||||
WriteUintToArr(Body, 0)
|
||||
}
|
||||
var Tr = { body: Body };
|
||||
this.CheckCreateTransactionObject(Tr)
|
||||
Arr.unshift(Tr)
|
||||
}
|
||||
}
|
||||
AddTransactionOwn(Tr) {
|
||||
if (!global.TX_PROCESS.Worker)
|
||||
return - 6;
|
||||
var StrHex = global.GetHexFromArr(sha3(Tr.body));
|
||||
global.TX_PROCESS.Worker.send({ cmd: "FindTX", TX: StrHex })
|
||||
return this.AddTransaction(Tr, 1);
|
||||
}
|
||||
};
|
||||
220
src/core/transfer-msg.ts
Normal file
220
src/core/transfer-msg.ts
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* @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";
|
||||
const MAX_MESSAGE_COUNT = 1000;
|
||||
module.exports = class CMessages extends require("./transaction-validator")
|
||||
{
|
||||
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) {
|
||||
super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
|
||||
this.MemPoolMsg = []
|
||||
for (var i = 0; i <= MAX_LEVEL_SPECIALIZATION; i++)
|
||||
this.MemPoolMsg[i] = new RBTree(CompareItemTimePow)
|
||||
}
|
||||
AddMsgToQuote(Msg) {
|
||||
var Tree = this.MemPoolMsg[Msg.Level];
|
||||
if (Tree) {
|
||||
if (Tree.insert(Msg)) {
|
||||
if (Tree.size > MEM_POOL_MSG_COUNT) {
|
||||
var maxitem = Tree.max();
|
||||
Tree.remove(maxitem)
|
||||
if (maxitem === Msg)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
IsValidMsg(Msg) {
|
||||
this.CheckCreateMsgHASH(Msg)
|
||||
if (Msg.power < MIN_POWER_POW_MSG)
|
||||
return - 1;
|
||||
if (Msg.time > this.CurrentBlockNum)
|
||||
return - 1;
|
||||
return 1;
|
||||
}
|
||||
CheckCreateMsgHASH(Msg) {
|
||||
if (!Msg.HashPow) {
|
||||
Msg.HASH = global.sha3(Msg.body)
|
||||
Msg.HashPow = GetHashWithValues(Msg.HASH, Msg.nonce, Msg.time)
|
||||
Msg.power = GetPowPower(Msg.HashPow)
|
||||
Msg.TimePow = Msg.time + Msg.power - Math.log2(Msg.body.length / 128)
|
||||
Msg.Level = AddrLevelArr(this.addrArr, Msg.addrArr)
|
||||
if (Msg.Level >= MAX_LEVEL_SPECIALIZATION)
|
||||
Msg.Level = MAX_LEVEL_SPECIALIZATION
|
||||
}
|
||||
}
|
||||
CreateMsgFromBody(Body, ToAddr) {
|
||||
var HASH = global.sha3(Body);
|
||||
var Msg = {
|
||||
HASH: HASH, body: Body, addrArr: ToAddr, nonce: CreateNoncePOWExtern(HASH, this.CurrentBlockNum, 3 * (1 << MIN_POWER_POW_MSG)),
|
||||
time: this.CurrentBlockNum,
|
||||
};
|
||||
this.CheckCreateMsgHASH(Msg)
|
||||
return Msg;
|
||||
}
|
||||
SendMessage(Body, ToAddr) {
|
||||
var Msg = this.CreateMsgFromBody(Body, ToAddr);
|
||||
this.SendMessageNext(Msg)
|
||||
}
|
||||
SendMessageNext(Msg) {
|
||||
var CountNodes = 3;
|
||||
var LevelStart = Msg.Level;
|
||||
if (global.CompareArr(this.addrArr, Msg.addrArr) === 0)
|
||||
return false;
|
||||
for (var L = LevelStart; L >= 0; L--)
|
||||
if (this.LevelNodes[L] && this.LevelNodes[L].length) {
|
||||
var arr = this.LevelNodes[L];
|
||||
for (var j = 0; arr && j < arr.length; j++) {
|
||||
var Node = arr[j];
|
||||
this.SendF(Node, { "Method": "MESSAGE", "Data": { Arr: [Msg] } })
|
||||
CountNodes--
|
||||
if (CountNodes <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
static
|
||||
MESSAGE_F() {
|
||||
return "{Arr:[{addrArr:hash,body:tr,nonce:uint,time:uint}]}";
|
||||
}
|
||||
MESSAGE(Info, CurTime) {
|
||||
var Data = this.DataFromF(Info);
|
||||
var arr = Data.Arr;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
var Msg = arr[i];
|
||||
if (this.IsValidMsg(Msg)) {
|
||||
if (global.CompareArr(this.addrArr, Msg.addrArr) === 0) {
|
||||
var App = DAppByType[Msg.body[0]];
|
||||
if (App) {
|
||||
App.OnMessage(Msg, BlockNum, i)
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.AddMsgToQuote(Msg) === 1) {
|
||||
this.SendMessageNext(Msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SendGetMessage(Node) {
|
||||
var Context = { "SendGetMessage": 1 };
|
||||
this.Send(Node, { "Method": "GETMESSAGE", "Context": Context, "Data": undefined })
|
||||
}
|
||||
GETMESSAGE(Info, CurTime) {
|
||||
var arr = [];
|
||||
var BufLength = 300;
|
||||
var Level = AddrLevelArr(this.addrArr, Info.Node.addrArr);
|
||||
var Tree = this.MemPoolMsg[Level];
|
||||
if (Tree) {
|
||||
var it = Tree.iterator(), Item;
|
||||
while ((Item = it.next()) !== null) {
|
||||
if (arr.length >= MAX_MESSAGE_COUNT)
|
||||
break;
|
||||
arr.push(Item)
|
||||
BufLength += Item.body.length + 50
|
||||
}
|
||||
}
|
||||
this.SendF(Info.Node, { "Method": "MESSAGE", "Context": Info.Context, "Data": { Arr: arr } }, BufLength)
|
||||
}
|
||||
AddTransaction(Tr, ToAll) {
|
||||
Tr.ToAll = ToAll
|
||||
var Res = this.IsValidTransaction(Tr, this.CurrentBlockNum);
|
||||
if (Res <= 0 && Res !== - 3)
|
||||
return Res;
|
||||
if (Tr.num < this.CurrentBlockNum)
|
||||
return - 3;
|
||||
var delta = Tr.num - this.CurrentBlockNum;
|
||||
if (delta > 3) {
|
||||
if (delta < 15) {
|
||||
let TR = Tr;
|
||||
let SELF = this;
|
||||
setTimeout(function() {
|
||||
var Res = SELF.AddTransaction(TR, TR.ToAll);
|
||||
if (TR.ToAll)
|
||||
ToLogClient("#3 Added " + TrName(TR) + " for block: " + TR.num + " on timer Res=" + Res)
|
||||
}, (delta - 3) * 1000)
|
||||
if (Tr.ToAll)
|
||||
ToLogClient("#2 Added " + TrName(Tr) + " for block: " + Tr.num + " to timer. Send transaction after " + (delta - 3) + " sec")
|
||||
return 4;
|
||||
}
|
||||
return - 3;
|
||||
}
|
||||
var Block = this.GetBlockContext(Tr.num);
|
||||
if (!Block)
|
||||
return - 5;
|
||||
if (Block.Active) {
|
||||
Res = - 3
|
||||
}
|
||||
else {
|
||||
Res = this.AddTrToBlockQuote(Block, Tr)
|
||||
if (Tr.ToAll)
|
||||
this.SendTransaction(Tr)
|
||||
}
|
||||
ToLogContext("#1 Add " + TrName(Tr) + " for Block: " + Tr.num + " Res=" + Res)
|
||||
return Res;
|
||||
}
|
||||
SendTransaction(Tr) {
|
||||
if (!Tr.ToAll)
|
||||
return;
|
||||
var CurTime = GetCurrentTime(0) - 0;
|
||||
var Count;
|
||||
if (GrayConnect())
|
||||
Count = Math.trunc(MAX_GRAY_CONNECTIONS_TO_SERVER / 2)
|
||||
else
|
||||
Count = Math.min(this.ActualNodes.size, 16)
|
||||
if (Count < 2)
|
||||
Count = 2
|
||||
var ArrNodes = this.GetActualNodes();
|
||||
for (var i = 0; i < ArrNodes.length; i++) {
|
||||
var Node = ArrNodes[i];
|
||||
if (!Node)
|
||||
continue;
|
||||
if (Node.TaskLastSend) {
|
||||
var Delta = CurTime - Node.TaskLastSend;
|
||||
if (Delta < global.PERIOD_GET_BLOCK || Node.StopGetBlock) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Node.TaskLastSend = CurTime
|
||||
this.SendF(Node, { "Method": "TRANSACTION", "Data": Tr }, Tr.body.length + 1000)
|
||||
ToLogContext("Send " + TrName(Tr) + " to " + NodeName(Node))
|
||||
Count--
|
||||
if (Count <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
static
|
||||
TRANSACTION_F() {
|
||||
return "{body:tr}";
|
||||
}
|
||||
TRANSACTION(Info, CurTime) {
|
||||
var Tr = this.DataFromF(Info);
|
||||
ToLogContext("Receive " + TrName(Tr) + " from " + NodeName(Info.Node))
|
||||
this.AddTransaction(Tr, 0)
|
||||
}
|
||||
};
|
||||
|
||||
function ToLogContext(Str) {
|
||||
};
|
||||
|
||||
function TrName(Tr) {
|
||||
if (!Tr.HASH)
|
||||
global.SERVER.CheckCreateTransactionObject(Tr);
|
||||
var Str = global.GetHexFromArr(Tr.HASH);
|
||||
return "Tx:" + Str.substr(0, 8);
|
||||
};
|
||||
global.TrName = TrName;
|
||||
165
src/core/update.ts
Normal file
165
src/core/update.ts
Normal file
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* @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
|
||||
*/
|
||||
|
||||
global.RunOnUpdate = RunOnUpdate;
|
||||
|
||||
function RunOnUpdate() {
|
||||
var fname = global.GetDataPath("DB/update.lst");
|
||||
var UpdateInfo = LoadParams(fname, { UPDATE_NUM_COMPLETE: 1071 });
|
||||
if (!UpdateInfo.UPDATE_NUM_COMPLETE)
|
||||
UpdateInfo.UPDATE_NUM_COMPLETE = 0;
|
||||
var CurNum = UpdateInfo.UPDATE_NUM_COMPLETE;
|
||||
if (CurNum !== UPDATE_CODE_VERSION_NUM) {
|
||||
UpdateInfo.UPDATE_NUM_COMPLETE = UPDATE_CODE_VERSION_NUM;
|
||||
global.ToLog("UPDATER Start");
|
||||
SaveParams(fname, UpdateInfo);
|
||||
if (global.TEST_NETWORK || global.LOCAL_RUN) {
|
||||
}
|
||||
else {
|
||||
}
|
||||
global.ToLog("UPDATER Finish");
|
||||
}
|
||||
};
|
||||
|
||||
function CreateHeadersHash100() {
|
||||
global.ToLog("CreateHeadersHash100");
|
||||
const DBRow = require("./db/db-row");
|
||||
global.UpdateMode = 1;
|
||||
var DB = global.SERVER.DBHeader100;
|
||||
var Num = 0;
|
||||
var PrevHash100 = [];
|
||||
while (1) {
|
||||
var Block = global.SERVER.ReadBlockHeaderDB(Num);
|
||||
if (!Block)
|
||||
break;
|
||||
var Hash100;
|
||||
if (Num === 0)
|
||||
Hash100 = [];
|
||||
else
|
||||
Hash100 = sha3arr2(PrevHash100, Block.Hash);
|
||||
DB.Write({ Num: Num / 100, Hash100: Hash100, Hash: Block.Hash });
|
||||
if (Num % 1000000 === 0)
|
||||
global.ToLog("Create Hash100:" + Num);
|
||||
PrevHash100 = Hash100;
|
||||
Num += 100;
|
||||
}
|
||||
global.UpdateMode = 0;
|
||||
};
|
||||
|
||||
function CheckRewriteTr(Num, StrHash, StartRewrite) {
|
||||
if (SERVER.BlockNumDB < StartRewrite)
|
||||
return "NO";
|
||||
var AccountsHash = global.DApps.Accounts.GetHashOrUndefined(Num);
|
||||
if (!AccountsHash || global.GetHexFromArr(AccountsHash) !== StrHash) {
|
||||
global.ToLog("START REWRITE ERR ACTS TRANSACTIONS");
|
||||
global.SERVER.ReWriteDAppTransactions(SERVER.BlockNumDB - StartRewrite);
|
||||
return "Rewrite";
|
||||
}
|
||||
else {
|
||||
return "OK";
|
||||
}
|
||||
};
|
||||
|
||||
function CheckRewriteAllTr2(Num, StrHash, Num2, StrHash2) {
|
||||
if (global.LOCAL_RUN || global.TEST_NETWORK)
|
||||
return "NONE";
|
||||
var MaxNum = global.SERVER.GetMaxNumBlockDB();
|
||||
if (MaxNum < START_BLOCK_ACCOUNT_HASH)
|
||||
return "NONE";
|
||||
var AccountsHash = global.DApps.Accounts.GetHashOrUndefined(Num);
|
||||
var AccountsHash2 = global.DApps.Accounts.GetHashOrUndefined(Num2);
|
||||
if (AccountsHash2 && global.GetHexFromArr(AccountsHash2) === StrHash2)
|
||||
return "OK";
|
||||
if (AccountsHash && global.GetHexFromArr(AccountsHash) !== StrHash) {
|
||||
global.ToLog("***************** START REWRITE ALL DAPPS");
|
||||
global.UpdateMode = 1;
|
||||
for (var key in DApps) {
|
||||
DApps[key].ClearDataBase();
|
||||
}
|
||||
global.UpdateMode = 0;
|
||||
return "Rewrite";
|
||||
}
|
||||
else {
|
||||
return "OK";
|
||||
}
|
||||
};
|
||||
|
||||
function CheckRewriteAllTr(Num, StrHash, Num2, StrHash2) {
|
||||
if (global.LOCAL_RUN || global.TEST_NETWORK)
|
||||
return "NONE";
|
||||
var MaxNum = global.SERVER.GetMaxNumBlockDB();
|
||||
if (MaxNum < START_BLOCK_ACCOUNT_HASH)
|
||||
return "NONE";
|
||||
var AccountsHash = global.DApps.Accounts.GetHashOrUndefined(Num);
|
||||
if (AccountsHash && global.GetHexFromArr(AccountsHash) !== StrHash) {
|
||||
global.ToLog("***************** START REWRITE ALL DAPPS");
|
||||
global.UpdateMode = 1;
|
||||
for (var key in DApps) {
|
||||
DApps[key].ClearDataBase();
|
||||
}
|
||||
global.UpdateMode = 0;
|
||||
return "Rewrite";
|
||||
}
|
||||
else {
|
||||
return "OK";
|
||||
}
|
||||
};
|
||||
global.CheckRewriteTr = CheckRewriteTr;
|
||||
|
||||
function RecreateAccountRest1() {
|
||||
var name = "accounts-rest";
|
||||
var fname = global.GetDataPath("DB/" + name);
|
||||
if (fs.existsSync(fname)) {
|
||||
global.ToLog("Delete " + fname);
|
||||
fs.unlinkSync(fname);
|
||||
}
|
||||
};
|
||||
|
||||
function RecreateAccountHashDB3() {
|
||||
var name = "accounts-hash2";
|
||||
var fname = global.GetDataPath("DB/" + name);
|
||||
if (fs.existsSync(fname)) {
|
||||
global.UpdateMode = 1;
|
||||
global.ToLog("Start updating " + name);
|
||||
const DBRow = require("../core/db/db-row");
|
||||
var DB0 = new DBRow(name, 6 + 32 + 32 + 10, "{BlockNum:uint, Hash:hash, SumHash:hash, Reserve: arr10}");
|
||||
var DB3 = global.DApps.Accounts.DBAccountsHash;
|
||||
for (var num = 0; true; num++) {
|
||||
var Item = DB0.Read(num);
|
||||
if (!Item)
|
||||
break;
|
||||
Item.AccHash = Item.Hash;
|
||||
DB3.Write(Item);
|
||||
}
|
||||
global.ToLog("Finish updating " + name);
|
||||
DB0.Close();
|
||||
DB3.Close();
|
||||
global.UpdateMode = 0;
|
||||
fs.unlinkSync(fname);
|
||||
}
|
||||
};
|
||||
|
||||
function ReWriteDBSmartWrite() {
|
||||
global.UpdateMode = 1;
|
||||
global.ToLog("Start ReWriteDBSmartWrite");
|
||||
require("../core/db/db-row");
|
||||
for (var num = 0; true; num++) {
|
||||
var Item = global.DApps.Smart.DBSmart.Read(num);
|
||||
if (!Item)
|
||||
break;
|
||||
var Body = (global.GetArrFromHex(GetBufferFromObject(Item, global.DApps.Smart.FORMAT_ROW, 20000, {});
|
||||
if (Body.length > 15000)
|
||||
global.ToLog("Smart " + Item.Num + ". " + Item.Name + " length=" + Body.length);
|
||||
global.DApps.Smart.DBSmartWrite(Item);
|
||||
}
|
||||
global.ToLog("Finish ReWriteDBSmartWrite");
|
||||
global.DApps.Smart.DBSmart.Close();
|
||||
global.UpdateMode = 0;
|
||||
};
|
||||
226
src/core/wallet.ts
Normal file
226
src/core/wallet.ts
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* @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";
|
||||
const fs = require('fs');
|
||||
import * as crypto from 'crypto';
|
||||
require("./library");
|
||||
require("./crypto-library");
|
||||
const WalletPath = "WALLET";
|
||||
const DBRow = require("./db/db-row");
|
||||
const CONFIG_NAME = global.GetDataPath(WalletPath + "/config.lst");
|
||||
class CApp {
|
||||
constructor() {
|
||||
CheckCreateDir(global.GetDataPath(WalletPath))
|
||||
var bReadOnly = (global.PROCESS_NAME !== "TX");
|
||||
this.Password = ""
|
||||
this.WalletOpen = undefined
|
||||
var Params = LoadParams(CONFIG_NAME, undefined);
|
||||
if (!Params) {
|
||||
Params = {}
|
||||
if (global.TEST_NETWORK) {
|
||||
Params.Key = global.ARR_PUB_KEY[0]
|
||||
}
|
||||
else {
|
||||
Params.Key = global.GetHexFromArr(crypto.randomBytes(32))
|
||||
}
|
||||
Params.AccountMap = {}
|
||||
Params.MiningAccount = 0
|
||||
}
|
||||
if (Params.MiningAccount)
|
||||
global.GENERATE_BLOCK_ACCOUNT = Params.MiningAccount
|
||||
this.AccountMap = Params.AccountMap
|
||||
this.KeyPair = crypto.createECDH('secp256k1')
|
||||
if (Params.Protect) {
|
||||
ToLogClient("Wallet protect by password")
|
||||
this.KeyXOR = global.GetArrFromHex(Params.KeyXOR)
|
||||
this.WalletOpen = false
|
||||
this.SetPrivateKey(Params.PubKey)
|
||||
}
|
||||
else {
|
||||
this.SetPrivateKey(Params.Key)
|
||||
}
|
||||
}
|
||||
SetMiningAccount(Account) {
|
||||
global.GENERATE_BLOCK_ACCOUNT = Account
|
||||
this.SaveWallet()
|
||||
}
|
||||
AddTransaction(Tr) {
|
||||
if (!global.TX_PROCESS.Worker)
|
||||
return 0;
|
||||
var StrHex = global.GetHexFromArr(sha3(Tr.body));
|
||||
global.TX_PROCESS.Worker.send({ cmd: "FindTX", TX: StrHex })
|
||||
return global.SERVER.AddTransaction(Tr, 1);
|
||||
}
|
||||
SetPrivateKey(KeyStr, bSetNew) {
|
||||
var bGo = 1;
|
||||
if (this.WalletOpen === false) {
|
||||
bGo = 0
|
||||
}
|
||||
if (KeyStr && KeyStr.length === 64 && bGo) {
|
||||
this.KeyPair.setPrivateKey(GetArr32FromHex(KeyStr))
|
||||
this.KeyPair.PubKeyArr = this.KeyPair.getPublicKey('', 'compressed')
|
||||
this.KeyPair.PubKeyStr = global.GetHexFromArr(this.KeyPair.PubKeyArr)
|
||||
this.KeyPair.PrivKeyStr = KeyStr.toUpperCase()
|
||||
this.KeyPair.addrArr = this.KeyPair.PubKeyArr.slice(1)
|
||||
this.KeyPair.addrStr = GetHexAddresFromPublicKey(this.KeyPair.addrArr)
|
||||
this.KeyPair.addr = this.KeyPair.addrArr
|
||||
this.KeyPair.WasInit = 1
|
||||
this.PubKeyArr = this.KeyPair.PubKeyArr
|
||||
}
|
||||
else {
|
||||
this.KeyPair.WasInit = 0
|
||||
if (KeyStr) {
|
||||
this.PubKeyArr = global.GetArrFromHex(KeyStr)
|
||||
this.KeyPair.PubKeyStr = global.GetHexFromArr(this.PubKeyArr)
|
||||
}
|
||||
else {
|
||||
this.PubKeyArr = []
|
||||
this.KeyPair.PubKeyStr = ""
|
||||
}
|
||||
this.KeyPair.PrivKeyStr = ""
|
||||
}
|
||||
if (bSetNew) {
|
||||
this.AccountMap = {}
|
||||
}
|
||||
this.FindMyAccounts(0)
|
||||
if (bGo)
|
||||
this.SaveWallet()
|
||||
}
|
||||
CloseWallet() {
|
||||
this.Password = ""
|
||||
this.WalletOpen = false
|
||||
this.KeyPair = crypto.createECDH('secp256k1')
|
||||
this.SetPrivateKey(GetHexFromArr(this.PubKeyArr), false)
|
||||
ToLogClient("Wallet close")
|
||||
return 1;
|
||||
}
|
||||
OpenWallet(StrPassword) {
|
||||
if (this.WalletOpen !== false) {
|
||||
ToLogClient("Wallet was open")
|
||||
}
|
||||
var Hash = this.HashProtect(StrPassword);
|
||||
var TestPrivKey = this.XORHash(this.KeyXOR, Hash, 32);
|
||||
if (!IsZeroArr(TestPrivKey)) {
|
||||
this.KeyPair.setPrivateKey(Buffer.from(TestPrivKey))
|
||||
var TestPubKey = this.KeyPair.getPublicKey('', 'compressed');
|
||||
if (global.CompareArr(TestPubKey, this.PubKeyArr) !== 0) {
|
||||
ToLogClient("Wrong password")
|
||||
return 0;
|
||||
}
|
||||
this.Password = StrPassword
|
||||
this.WalletOpen = true
|
||||
this.SetPrivateKey(GetHexFromArr(TestPrivKey), false)
|
||||
}
|
||||
else {
|
||||
this.Password = StrPassword
|
||||
this.WalletOpen = true
|
||||
this.SetPrivateKey(GetHexFromArr(this.PubKeyArr), false)
|
||||
}
|
||||
ToLogClient("Wallet open")
|
||||
return 1;
|
||||
}
|
||||
SetPasswordNew(StrPassword) {
|
||||
if (this.WalletOpen === false) {
|
||||
ToLogClient("Wallet is close by password")
|
||||
return;
|
||||
}
|
||||
this.Password = StrPassword
|
||||
if (StrPassword)
|
||||
this.WalletOpen = true
|
||||
else
|
||||
this.WalletOpen = undefined
|
||||
this.SaveWallet()
|
||||
}
|
||||
HashProtect(Str) {
|
||||
var arr = global.shaarr(Str);
|
||||
for (var i = 0; i < 10000; i++) {
|
||||
arr = global.shaarr(arr)
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
XORHash(arr1, arr2, length) {
|
||||
var arr3 = [];
|
||||
for (var i = 0; i < length; i++) {
|
||||
arr3[i] = arr1[i] ^ arr2[i]
|
||||
}
|
||||
return arr3;
|
||||
}
|
||||
SaveWallet() {
|
||||
if (this.WalletOpen === false) {
|
||||
return;
|
||||
}
|
||||
var Params = {};
|
||||
if (this.Password) {
|
||||
Params.Protect = true
|
||||
var Hash = this.HashProtect(this.Password);
|
||||
if (this.KeyPair.WasInit) {
|
||||
Params.KeyXOR = global.GetHexFromArr(this.XORHash(this.KeyPair.getPrivateKey(), Hash, 32))
|
||||
}
|
||||
else {
|
||||
var Key2 = [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];
|
||||
Params.KeyXOR = global.GetHexFromArr(this.XORHash(Key2, Hash, 32))
|
||||
}
|
||||
Params.PubKey = global.GetHexFromArr(this.PubKeyArr)
|
||||
this.KeyXOR = global.GetArrFromHex(Params.KeyXOR)
|
||||
}
|
||||
else {
|
||||
if (this.KeyPair.WasInit)
|
||||
Params.Key = this.KeyPair.PrivKeyStr
|
||||
else
|
||||
Params.Key = global.GetHexFromArr(this.PubKeyArr)
|
||||
}
|
||||
Params.AccountMap = this.AccountMap
|
||||
Params.MiningAccount = global.GENERATE_BLOCK_ACCOUNT
|
||||
SaveParams(CONFIG_NAME, Params)
|
||||
}
|
||||
OnCreateAccount(Data) {
|
||||
this.AccountMap[Data.Num] = 0
|
||||
}
|
||||
FindMyAccounts(bClean) {
|
||||
if (IsZeroArr(this.PubKeyArr))
|
||||
return;
|
||||
if (bClean)
|
||||
this.AccountMap = {}
|
||||
global.DApps.Accounts.FindAccounts([this.PubKeyArr], this.AccountMap, 0)
|
||||
}
|
||||
GetAccountKey(Num) {
|
||||
if (this.KeyPair.WasInit && global.TestTestWaletMode) {
|
||||
}
|
||||
return this.KeyPair;
|
||||
}
|
||||
GetPrivateKey(Num) {
|
||||
if (!this.KeyPair.WasInit)
|
||||
return [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 KeyPair;
|
||||
if (Num) {
|
||||
KeyPair = this.GetAccountKey(Num)
|
||||
}
|
||||
else {
|
||||
KeyPair = this.KeyPair
|
||||
}
|
||||
return KeyPair.getPrivateKey();
|
||||
}
|
||||
GetSignFromArr(Arr, Num) {
|
||||
if (!this.KeyPair.WasInit)
|
||||
return "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||
var PrivKey = this.GetPrivateKey(Num);
|
||||
var sigObj = secp256k1.sign(SHA3BUF(Arr), Buffer.from(PrivKey));
|
||||
returnglobal.GetHexFromArr(sigObj.signature);
|
||||
}
|
||||
GetSignTransaction(TR) {
|
||||
if (!this.KeyPair.WasInit)
|
||||
return "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
|
||||
var PrivKey = this.GetPrivateKey(this.AccountMap[TR.FromID]);
|
||||
var Arr = global.DApps.Accounts.GetSignTransferTx(TR, PrivKey);
|
||||
returnglobal.GetHexFromArr(Arr);
|
||||
}
|
||||
};
|
||||
global.WALLET = new CApp;
|
||||
Reference in New Issue
Block a user