feat: first commit

Signed-off-by: MiaoWoo <admin@yumc.pw>
This commit is contained in:
2019-07-10 12:01:15 +08:00
commit cbc0ed72c4
134 changed files with 47644 additions and 0 deletions

View 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) };
};

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

File diff suppressed because it is too large Load Diff

364
src/core/buffer.ts Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

352
src/core/constant.ts Normal file
View 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
View 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

File diff suppressed because it is too large Load Diff

229
src/core/db/db-row.ts Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

424
src/core/library.ts Normal file
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

46
src/core/startlib.ts Normal file
View 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
View 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 };
};

View 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
View 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
View 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
View 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;