forked from circlecloud/tera
		
	
		
			
				
	
	
		
			345 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			345 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
/*
 | 
						|
 * @project: TERA
 | 
						|
 * @version: Development (beta)
 | 
						|
 * @license: MIT (not for evil)
 | 
						|
 * @copyright: Yuriy Ivanov (Vtools) 2017-2019 [progr76@gmail.com]
 | 
						|
 * Web: https://terafoundation.org
 | 
						|
 * Twitter: https://twitter.com/terafoundation
 | 
						|
 * Telegram:  https://t.me/terafoundation
 | 
						|
*/
 | 
						|
 | 
						|
global.PROCESS_NAME = "STATIC";
 | 
						|
import * as crypto from 'crypto';
 | 
						|
import * as fs from 'fs'
 | 
						|
import "../core/constant"
 | 
						|
import '../core/block-loader-const'
 | 
						|
import '../core/rest_tables'
 | 
						|
import '../system/accounts'
 | 
						|
import '../system/smart'
 | 
						|
global.DATA_PATH = global.GetNormalPathString(global.DATA_PATH);
 | 
						|
global.CODE_PATH = global.GetNormalPathString(global.CODE_PATH);
 | 
						|
import "../core/library"
 | 
						|
import "./child-process"
 | 
						|
global.READ_ONLY_DB = 1;
 | 
						|
 | 
						|
process.on('message', function(msg) {
 | 
						|
    switch (msg.cmd) {
 | 
						|
        case "GETBLOCKHEADER":
 | 
						|
            GETBLOCKHEADER(msg);
 | 
						|
            break;
 | 
						|
        case "GETBLOCKHEADER100":
 | 
						|
            GETBLOCKHEADER100(msg);
 | 
						|
            break;
 | 
						|
        case "GETBLOCK":
 | 
						|
            GETBLOCK(msg);
 | 
						|
            break;
 | 
						|
        case "GETCODE":
 | 
						|
            GETCODE(msg);
 | 
						|
            break;
 | 
						|
        case "GETREST":
 | 
						|
            GETREST(msg);
 | 
						|
            break;
 | 
						|
        case "GETSMART":
 | 
						|
            GETSMART(msg);
 | 
						|
            break;
 | 
						|
    }
 | 
						|
});
 | 
						|
 | 
						|
import CServerDB from '../core/db/block-db'
 | 
						|
import { DB_FORMAT } from '../constant/db-format';
 | 
						|
var KeyPair = crypto.createECDH('secp256k1');
 | 
						|
KeyPair.setPrivateKey(Buffer.from([77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77]));
 | 
						|
global.SERVER = new CServerDB(KeyPair, undefined, undefined, false, true);
 | 
						|
global.HTTP_PORT_NUMBER = 0;
 | 
						|
setInterval(function() {
 | 
						|
    if (global.SERVER)
 | 
						|
        global.SERVER.Close();
 | 
						|
    global.DApps.Accounts.Close();
 | 
						|
    global.DApps.Smart.DBSmart.Close();
 | 
						|
}, 1000);
 | 
						|
 | 
						|
function GETBLOCKHEADER100(msg) {
 | 
						|
    return;
 | 
						|
    var Data = msg.Data;
 | 
						|
    var BlockNum = Data.BlockNum;
 | 
						|
    if (BlockNum % 100 !== 0)
 | 
						|
        return;
 | 
						|
    var EndNum100 = BlockNum / 100;
 | 
						|
    var LoadHash100 = Data.Hash;
 | 
						|
    var Hash100;
 | 
						|
    var Count = Data.Count;
 | 
						|
    if (!Count || Count < 0 || !EndNum100)
 | 
						|
        return;
 | 
						|
    if (Count > global.COUNT_BLOCKS_FOR_LOAD)
 | 
						|
        Count = global.COUNT_BLOCKS_FOR_LOAD;
 | 
						|
    var Arr = [];
 | 
						|
    var Data100 = global.SERVER.DBHeader100.Read(EndNum100);
 | 
						|
    if (Data100 && global.CompareArr(Data100.Hash100, LoadHash100) === 0) {
 | 
						|
        var StartNum = EndNum100 - Count + 1;
 | 
						|
        if (StartNum < 0)
 | 
						|
            StartNum = 0;
 | 
						|
        for (var Num = StartNum; Num <= EndNum100; Num++) {
 | 
						|
            Data100 = global.SERVER.DBHeader100.Read(Num);
 | 
						|
            if (Num === StartNum)
 | 
						|
                Arr.push(Data100.Hash100);
 | 
						|
            Arr.push(Data100.Hash);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    var BufWrite = global.BufLib.GetBufferFromObject(Arr, "[hash]", global.MAX_PACKET_LENGTH, {});
 | 
						|
    global.ToLog("GETBLOCKHEADER100 Send Arr=" + Arr.length + " - " + BlockNum);
 | 
						|
    process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETBLOCKHEADER100", Context: msg.Context, Data: BufWrite });
 | 
						|
};
 | 
						|
 | 
						|
function GETBLOCKHEADER(msg) {
 | 
						|
    var Data = msg.Data;
 | 
						|
    var StartNum = undefined;
 | 
						|
    var BlockNum;
 | 
						|
    var LoadHash = Data.Hash;
 | 
						|
    var Foward = Data.Foward;
 | 
						|
    if (Foward) {
 | 
						|
        var BlockDB = global.SERVER.ReadBlockHeaderDB(Data.BlockNum);
 | 
						|
        if (BlockDB && BlockDB.SumHash && (global.CompareArr(BlockDB.SumHash, LoadHash) === 0 || global.IsZeroArr(LoadHash))) {
 | 
						|
            StartNum = Data.BlockNum - global.BLOCK_PROCESSING_LENGTH2;
 | 
						|
            if (StartNum < 0)
 | 
						|
                StartNum = 0;
 | 
						|
            BlockNum = StartNum + global.COUNT_BLOCKS_FOR_LOAD + global.BLOCK_PROCESSING_LENGTH2;
 | 
						|
            if (BlockNum > global.SERVER.GetMaxNumBlockDB())
 | 
						|
                BlockNum = global.SERVER.GetMaxNumBlockDB();
 | 
						|
        }
 | 
						|
    } else {
 | 
						|
        BlockNum = Data.BlockNum;
 | 
						|
        var IsSum = Data.IsSum;
 | 
						|
        var Count = Data.Count;
 | 
						|
        if (!Count || Count < 0 || BlockNum < 0)
 | 
						|
            return;
 | 
						|
        if (Count > global.COUNT_BLOCKS_FOR_LOAD)
 | 
						|
            Count = global.COUNT_BLOCKS_FOR_LOAD;
 | 
						|
        Count += global.BLOCK_PROCESSING_LENGTH2;
 | 
						|
        var BlockDB = global.SERVER.ReadBlockHeaderDB(BlockNum);
 | 
						|
        if (BlockDB && (BlockDB.Prepared && (!IsSum) && BlockDB.Hash && global.CompareArr(BlockDB.Hash, LoadHash) === 0 || BlockDB.bSave && IsSum && BlockDB.SumHash && global.CompareArr(BlockDB.SumHash,
 | 
						|
            LoadHash) === 0)) {
 | 
						|
            StartNum = BlockNum - Count + 1;
 | 
						|
            if (StartNum < 0)
 | 
						|
                StartNum = 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    var BufWrite = global.SERVER.BlockChainToBuf(StartNum, StartNum, BlockNum);
 | 
						|
    process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETBLOCKHEADER", Context: msg.Context, Data: BufWrite });
 | 
						|
};
 | 
						|
 | 
						|
function GETBLOCK(msg) {
 | 
						|
    var Data = msg.Data;
 | 
						|
    var BlockNum = Data.BlockNum;
 | 
						|
    var TreeHash = Data.TreeHash;
 | 
						|
    if (msg.Context.SendCount) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    var BufWrite: Buffer;
 | 
						|
    var BlockDB = global.SERVER.ReadBlockDB(BlockNum);
 | 
						|
    var StrSend;
 | 
						|
    if (BlockDB && (global.CompareArr(BlockDB.TreeHash, TreeHash) === 0 || global.IsZeroArr(TreeHash))) {
 | 
						|
        var BufWrite = global.BufLib.GetBufferFromObject(BlockDB, DB_FORMAT.FORMAT_BLOCK_TRANSFER, global.MAX_PACKET_LENGTH, global.WRK_BLOCK_TRANSFER);
 | 
						|
        StrSend = "OK";
 | 
						|
    }
 | 
						|
    if (StrSend === "OK") {
 | 
						|
        global.ADD_TO_STAT("BLOCK_SEND");
 | 
						|
    }
 | 
						|
    else {
 | 
						|
        BufWrite = global.BufLib.GetNewBuffer(100);
 | 
						|
        StrSend = "NO";
 | 
						|
    }
 | 
						|
    process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETGETBLOCK", Context: msg.Context, Data: BufWrite });
 | 
						|
};
 | 
						|
 | 
						|
function GETCODE(msg) {
 | 
						|
    var VersionNum = msg.Data;
 | 
						|
    var fname = global.GetDataPath("Update/wallet-" + VersionNum + ".zip");
 | 
						|
    if (fs.existsSync(fname)) {
 | 
						|
        var data = fs.readFileSync(fname);
 | 
						|
        process.send({ cmd: "Send", addrStr: msg.addrStr, Method: "RETCODE", Context: msg.Context, Data: data });
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
function GETREST(msg) {
 | 
						|
    var Data = msg.Data;
 | 
						|
    if (!Data.BlockNum)
 | 
						|
        return;
 | 
						|
    if (global.IsZeroArr(Data.AccHash)) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    var BlockNumRest = Data.BlockNum;
 | 
						|
    var RestIndexArr = GetCurrentRestArr();
 | 
						|
    var nResult = 0;
 | 
						|
    for (var i = 0; i < RestIndexArr.length; i++) {
 | 
						|
        if (RestIndexArr[i] === BlockNumRest) {
 | 
						|
            nResult = 1;
 | 
						|
            break;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    var BufLength = 1000;
 | 
						|
    var ProofHash = [];
 | 
						|
    var ProofArrL = [];
 | 
						|
    var ProofArrR = [];
 | 
						|
    var ArrRest = [];
 | 
						|
    if (nResult) {
 | 
						|
        var WorkStruct = {};
 | 
						|
        var WorkFormat = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
 | 
						|
        var WorkFormatLength = global.DApps.Accounts.SIZE_ACCOUNT_ROW;
 | 
						|
        var Max = global.DApps.Accounts.DBState.GetMaxNum();
 | 
						|
        var LengthAccount = Data.Count;
 | 
						|
        if (LengthAccount > global.MAX_ACCOUNTS_TRANSFER)
 | 
						|
            LengthAccount = global.MAX_ACCOUNTS_TRANSFER;
 | 
						|
        var StartAccount = Data.AccNum;
 | 
						|
        var EndAccount = StartAccount + LengthAccount - 1;
 | 
						|
        if (EndAccount > Max)
 | 
						|
            EndAccount = Max;
 | 
						|
        var Tree = GetRestMerkleTree(BlockNumRest, RestIndexArr);
 | 
						|
        if (global.CompareArr(Data.AccHash, Tree.Root) !== 0) {
 | 
						|
            global.ToLog("Get bad rest acc hash: " + BlockNumRest + " = " + global.GetHexFromArr(Data.AccHash) + "/" + global.GetHexFromArr(Tree.Root), 2);
 | 
						|
            ArrRest = [];
 | 
						|
            nResult = 0;
 | 
						|
        } else {
 | 
						|
            ArrRest = GetArrRest(BlockNumRest, StartAccount, EndAccount);
 | 
						|
            ProofHash = Tree.Root;
 | 
						|
            var RetProof = global.GetMerkleProof(Tree.LevelsHash, StartAccount, EndAccount);
 | 
						|
            ProofArrL = RetProof.ArrL;
 | 
						|
            ProofArrR = RetProof.ArrR;
 | 
						|
            BufLength = 1000 + ArrRest.length * WorkFormatLength;
 | 
						|
            BufLength += ProofArrL.length * 32 + ProofArrR.length * 32 + 32;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    var Data2 = {
 | 
						|
        Result: nResult,
 | 
						|
        Arr: ArrRest,
 | 
						|
        Version: 1,
 | 
						|
        ProofHash: ProofHash,
 | 
						|
        ProofArrL: ProofArrL,
 | 
						|
        ProofArrR: ProofArrR
 | 
						|
    };
 | 
						|
    var BufWrite = global.BufLib.GetBufferFromObject(Data2, DB_FORMAT.FORMAT_REST_TRANSFER, BufLength, {});
 | 
						|
    process.send({
 | 
						|
        cmd: "Send",
 | 
						|
        addrStr: msg.addrStr,
 | 
						|
        Method: "RETREST",
 | 
						|
        Context: msg.Context,
 | 
						|
        Data: BufWrite
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
function GETSMART(msg) {
 | 
						|
    var Data = msg.Data;
 | 
						|
    if (!Data.Count)
 | 
						|
        return;
 | 
						|
    var BufLength = 1000;
 | 
						|
    var SizeForSend = 200 * 1024;
 | 
						|
    var Arr = [];
 | 
						|
    for (var Num = Data.SmartNum; Num < Data.SmartNum + Data.Count; Num++) {
 | 
						|
        var BufSmart = global.DApps.Smart.DBSmart.Read(Num, 1);
 | 
						|
        if (!BufSmart)
 | 
						|
            break;
 | 
						|
        SizeForSend = SizeForSend - BufSmart.length;
 | 
						|
        if (SizeForSend < 0)
 | 
						|
            break;
 | 
						|
        BufLength += BufSmart.length;
 | 
						|
        Arr.push(BufSmart);
 | 
						|
    }
 | 
						|
    var Data2 = { Result: Arr.length ? 1 : 0, Arr: Arr };
 | 
						|
    var BufWrite = global.BufLib.GetBufferFromObject(Data2, DB_FORMAT.FORMAT_SMART_TRANSFER, BufLength, {});
 | 
						|
    process.send({
 | 
						|
        cmd: "Send",
 | 
						|
        addrStr: msg.addrStr,
 | 
						|
        Method: "RETSMART",
 | 
						|
        Context: msg.Context,
 | 
						|
        Data: BufWrite
 | 
						|
    });
 | 
						|
};
 | 
						|
var glMapForHash = {};
 | 
						|
 | 
						|
function GetArrRest(BlockNumRest, StartAccount, EndAccount, bHashOnly?) {
 | 
						|
    var ArrRest = [];
 | 
						|
    var WorkStruct = {};
 | 
						|
    var WorkFormat = global.DApps.Accounts.FORMAT_ACCOUNT_ROW;
 | 
						|
    var WorkFormatLength = global.DApps.Accounts.SIZE_ACCOUNT_ROW;
 | 
						|
    for (var Num = StartAccount; Num <= EndAccount; Num++) {
 | 
						|
        var FindItem = undefined;
 | 
						|
        var RestData = global.DApps.Accounts.ReadRest(Num);
 | 
						|
        var CountZero = 0;
 | 
						|
        for (var i = RestData.Arr.length - 1; i >= 0; i--) {
 | 
						|
            var Item = RestData.Arr[i];
 | 
						|
            if (!Item.BlockNum) {
 | 
						|
                CountZero++;
 | 
						|
                continue;
 | 
						|
            }
 | 
						|
            if (Item.BlockNum <= BlockNumRest) {
 | 
						|
                if (!FindItem || Item.BlockNum > FindItem.BlockNum) {
 | 
						|
                    FindItem = Item;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        var BlocNumMap = 0;
 | 
						|
        var StateDataValue = undefined;
 | 
						|
        if (FindItem) {
 | 
						|
            StateDataValue = FindItem.Value;
 | 
						|
            BlocNumMap = Item.BlockNum;
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            if (CountZero !== RestData.Arr.length)
 | 
						|
                continue;
 | 
						|
        }
 | 
						|
        var StateData = global.DApps.Accounts.DBState.Read(Num);
 | 
						|
        if (!StateData)
 | 
						|
            break;
 | 
						|
        if (StateDataValue)
 | 
						|
            StateData.Value = StateDataValue;
 | 
						|
        if (bHashOnly) {
 | 
						|
            var key = "" + Num + "-" + BlocNumMap;
 | 
						|
            var Hash = glMapForHash[key];
 | 
						|
            if (!Hash) {
 | 
						|
                var Buf = global.BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
 | 
						|
                Hash = global.shaarr(Buf);
 | 
						|
                glMapForHash[key] = Hash;
 | 
						|
            }
 | 
						|
            ArrRest.push(Hash);
 | 
						|
        }
 | 
						|
        else {
 | 
						|
            var Buf = global.BufLib.GetBufferFromObject(StateData, WorkFormat, WorkFormatLength, WorkStruct);
 | 
						|
            ArrRest.push(Buf);
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return ArrRest;
 | 
						|
};
 | 
						|
var glMapRest = {};
 | 
						|
 | 
						|
function GetRestMerkleTree(BlockNumRest, RestIndexArr) {
 | 
						|
    var MerkleTree = glMapRest[BlockNumRest];
 | 
						|
    if (!MerkleTree) {
 | 
						|
        global.ToLog("Create new glMapRest key: " + BlockNumRest, 2);
 | 
						|
        var startTime = process.hrtime();
 | 
						|
        var EndAccount = global.DApps.Accounts.DBState.GetMaxNum();
 | 
						|
        var ArrHash = GetArrRest(BlockNumRest, 0, EndAccount, 1);
 | 
						|
        var Time1 = process.hrtime(startTime);
 | 
						|
        var MerkleCalc = {};
 | 
						|
        MerkleTree = { LevelsHash: [ArrHash], RecalcCount: 0 };
 | 
						|
        for (var Num = 0; Num < ArrHash.length; Num++) {
 | 
						|
            MerkleCalc[Num] = 1;
 | 
						|
        }
 | 
						|
        global.UpdateMerklTree(MerkleTree, MerkleCalc, 0);
 | 
						|
        glMapRest[BlockNumRest] = MerkleTree;
 | 
						|
        var Time2 = process.hrtime(startTime);
 | 
						|
        var deltaTime1 = (Time1[0] * 1000 + Time1[1] / 1e6) / 1000;
 | 
						|
        var deltaTime2 = (Time2[0] * 1000 + Time2[1] / 1e6) / 1000;
 | 
						|
        global.ToLog("Create delta time: " + deltaTime1 + "/" + deltaTime2 + " s   Tree.Root=" + global.GetHexFromArr(MerkleTree.Root), 2);
 | 
						|
        var MapIndex = {};
 | 
						|
        for (var i = 0; i < RestIndexArr.length; i++) {
 | 
						|
            MapIndex[RestIndexArr[i]] = 1;
 | 
						|
        }
 | 
						|
        for (var key in glMapRest) {
 | 
						|
            if (!MapIndex[key]) {
 | 
						|
                global.ToLog("Delete old glMapRest key: " + key, 2);
 | 
						|
                delete glMapRest[key];
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return MerkleTree;
 | 
						|
};
 |