tera/src/core/transaction-validator.ts

222 lines
8.2 KiB
TypeScript
Raw Normal View History

/*
* @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);
}
};