/* * @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") { BufHashTree constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) { super(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual) this.BufHashTree = new global.RBTree(global.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 global.DApps) { global.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 = global.DAppByType[type]; if (App) { App.ResultTx = 0 global.DApps.Accounts.BeginTransaction() var StrHex = global.GetHexFromArr(global.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 (!global.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 global.DApps) { global.DApps[key].OnWriteBlockFinish(Block) } } BlockDeleteTX(Block) { this.BufHashTree.LastAddNum = 0 for (var key in global.DApps) { global.DApps[key].OnDeleteBlock(Block) } } OnDelete(Block) { } IsValidTicket(Tr, BlockNum) { this.CheckCreateTicketObject(Tr, BlockNum) if (Tr.power < global.MIN_POWER_POW_TR) return - 2; if (Tr.num !== BlockNum) return - 3; return 1; } IsValidTransaction(Tr, BlockNum) { if (!Tr.body || Tr.body.length < global.MIN_TRANSACTION_SIZE || Tr.body.length > global.MAX_TRANSACTION_SIZE) return - 1; this.CheckCreateTransactionObject(Tr) if (Tr.power - Math.log2(Tr.body.length / 128) < global.MIN_POWER_POW_TR) return - 2; if (Tr.num !== BlockNum) return - 3; if (Tr.body[0] === global.TYPE_TRANSACTION_ACC_HASH) return - 4; return 1; } ReWriteDAppTransactions(Length) { if (!global.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 % global.PERIOD_ACCOUNT_HASH !== 0) return; var BlockNumHash = BlockNum - global.DELTA_BLOCK_ACCOUNT_HASH; if (BlockNumHash < 0) return; var Item = global.DApps.Accounts.GetAccountHashItem(BlockNumHash); if (Item) { var Body = [global.TYPE_TRANSACTION_ACC_HASH]; global.WriteUintToArr(Body, BlockNumHash) global.WriteArrToArr(Body, Item.AccHash, 32) if (BlockNumHash >= global.START_BLOCK_ACCOUNT_HASH3) { global.WriteUintToArr(Body, Item.AccountMax) global.WriteArrToArr(Body, Item.SmartHash, 32) global.WriteUintToArr(Body, Item.SmartCount) global.WriteUintToArr(Body, BlockNum) global.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(global.sha3(Tr.body)); global.TX_PROCESS.Worker.send({ cmd: "FindTX", TX: StrHex }) return this.AddTransaction(Tr, 1); } };