tera/Source/core/code.js
progr76@gmail.com 3029d69c0e 0.884
2019-02-10 22:53:54 +03:00

247 lines
7.3 KiB
JavaScript

/*
* @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
*/
"use strict";
var fs = require("fs");
const FORMAT_EVAL_SEND = "{MaxBlockNum:uint,Code:str,Sign:arr64}";
module.exports = class CCode extends require("./base")
{
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
CheckCreateDir(GetDataPath("Update"))
}
CheckLoadCodeTime()
{
if(START_LOAD_CODE.StartLoadNode && START_LOAD_CODE.StartLoadVersionNum)
{
var Delta = new Date() - START_LOAD_CODE.StartLoadVersionNumTime;
if(Delta > 20 * 1000)
{
ToError("Cannot load code version:" + START_LOAD_CODE.StartLoadVersionNum + " from node: " + START_LOAD_CODE.StartLoadNode.ip + ":" + START_LOAD_CODE.StartLoadNode.port)
this.ClearLoadCode()
}
}
}
ClearLoadCode()
{
START_LOAD_CODE.StartLoad = undefined
START_LOAD_CODE.StartLoadVersionNum = 0
START_LOAD_CODE.StartLoadVersionNumTime = 0
}
StartLoadCode(Node, CodeVersion)
{
var VersionNum = CodeVersion.VersionNum;
START_LOAD_CODE.StartLoad = CodeVersion
START_LOAD_CODE.StartLoadNode = Node
START_LOAD_CODE.StartLoadVersionNum = VersionNum
START_LOAD_CODE.StartLoadVersionNumTime = new Date()
var fname = 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 || !START_LOAD_CODE.StartLoad)
return ;
var fname = GetDataPath("Update/wallet-" + VersionNum + ".zip");
if(!fs.existsSync(fname))
{
var Hash = shaarr(Info.Data);
if(CompareArr(Hash, 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
{
ToError("Error check hash of version code :" + 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.START_LOAD_CODE.StartLoad)
{
global.CODE_VERSION = START_LOAD_CODE.StartLoad
this.ClearLoadCode()
}
}
SetNewCodeVersion(Data, PrivateKey)
{
var fname = GetDataPath("ToUpdate/wallet.zip");
if(fs.existsSync(fname))
{
var fname2 = GetDataPath("Update/wallet-" + Data.VersionNum + ".zip");
if(fs.existsSync(fname2))
{
fs.unlinkSync(fname2)
}
var data = fs.readFileSync(fname);
var Hash = 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(shabuf(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 = 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;
ToLog("Check file:" + Name);
if(fs.existsSync(Path))
{
if(StartNum === Num)
{
ToLog("UnpackCodeFile:" + Name);
UnpackCodeFile(Path);
if(StartNum % 2 === 0)
{
global.RestartNode(1);
}
else
{
global.UPDATE_CODE_VERSION_NUM = Num;
}
return 1;
}
else
{
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();
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();
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();
ToLog("****************************************** RESTART!!!");
ToLog("EXIT 1");
};
function DoExit()
{
ToLog("EXIT 2");
if(global.nw || global.NWMODE)
{
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});
}
ToLog("EXIT 3");
process.exit(0);
};