1
0
Fork 0
merge-requests/3/head
progr76@gmail.com 2019-04-05 13:13:44 +03:00
parent be1548fa14
commit b70859c5a1
84 changed files with 3679 additions and 1383 deletions

Binary file not shown.

Binary file not shown.

View File

@ -2,6 +2,31 @@
This API is available if the node is running public http-access. Set the constant HTTP_HOSTING_PORT.
DappStaticCall - call static method
Example (GET)
```js
http://dappsgate.com:88/api/v1/DappStaticCall?MethodName=Test&Account=540
```
Example (POST)
```js
http://dappsgate.com:88/api/v1/DappStaticCall
{
"MethodName": "Test",
"Account":540
}```
return value:
```js
{"result":1,"RetValue":"Test-ok"}
```
see smart code of this example:
http://dappsgate.com:88/smart/200
#### Getting the current status of the blockchain
http://194.1.237.94/api/v1/GetCurrentInfo

View File

@ -1,5 +1,5 @@
# API v2 (for exchanges)
Works with update version 0.901
Works with update version 0.991
The API is designed to make it easier to write third-party applications. Server-side cryptography and POW operations are performed. Therefore, it is not recommended for public access, because it is not protected from DDOS attacks. Use it if applications such as the exchange server are on the same private network.
@ -12,6 +12,10 @@ This API is available if server is running http and hosting included constant US
Although the API is designed for use in POST requests, it can be used for GET requests in a limited mode.
Warning: the Tera blockchain has a high rate of block confirmation (starting from 4 seconds), but since it uses PoW, it is possible to get into local orphan chains. Therefore, for a reliable transfer of value, we recommend that exchanges wait for additional time, such as 100 seconds, to interpret the finality of the transaction.
Call format:
```js
{{Server}}/api/v2/{{MethodName}}
@ -231,6 +235,7 @@ return:
#### Parameters:
* AccountID - account (account) number)
* Count - maximum number of rows returned - history depth (default 100)
* Confirm - min confirm for return tx (default 8)
option to set parameters for organizing page navigation:
* NextPos - history line ID number (this value is taken from the last line of the previous result)

View File

@ -2,6 +2,32 @@
Данный API доступен если на ноде запущен публичный http-доступ. Т.е. задана константа HTTP_HOSTING_PORT
DappStaticCall - статический вызов метода смарт-контракта
Example (GET)
```js
http://dappsgate.com:88/api/v1/DappStaticCall?MethodName=Test&Account=540
```
Example (POST)
```js
http://dappsgate.com:88/api/v1/DappStaticCall
{
"MethodName": "Test",
"Account":540
}```
return value:
```js
{"result":1,"RetValue":"Test-ok"}
```
see smart code of this example:
http://dappsgate.com:88/smart/200
#### Получение текущего статуса блокчейна
http://194.1.237.94/GetCurrentInfo?Diagram=0

View File

@ -1,5 +1,5 @@
# API v2 (для бирж и обменников)
Работает с версии обновления 0.901
Работает с версии обновления 0.991
API предназначено для облегчения написания сторонних приложений. На стороне сервера выполняется криптография и операции POW. Поэтому оно не рекомендуется для публичного доступа, т.к. нет защиты от DDOS атак. Используйте его, если приложения такие как сервер биржи находятся в одной приватной сети.
@ -12,6 +12,10 @@ API предназначено для облегчения написания с
Несмотря на то что API разработано для использования в POST запросах, в ограниченном режиме его можно использовать для GET запросов.
Предупреждение: блокчейн Тера имеет высокую скорость подтверждения блока (начиная от 4 сек), но т.к. он использует PoW, то возможно попадание в локальные орфан цепочки. Поэтому для надежной передачи ценности мы рекомендуем биржам выжидать дополнительное время, например 100 секунд, для интерпретации финальности транзакции.
Формат вызова
```js
{{Server}}/api/v2/{{MethodName}}
@ -239,6 +243,7 @@ return:
#### Параметры:
* AccountID - номер счета (аккаунта)
* Count - максимальное число возвращаемых строк - глубина истории (по умолчанию 100)
* Confirm - min число подтверждений требуемых, чтобы транзакция попала в результат выдачи (по умолчанию 8)
вариант задания параметров для организации постраничной навигации:
* NextPos - номер ид строки истории (это значение берется из последней строки предыдущего результата)

View File

@ -20,7 +20,6 @@ body
body.styleBrown
{
--colorText:#FFF;
--color0:#503F13;
--color1:#86754A;
--color2:#F5E5BB;

View File

@ -940,16 +940,21 @@ function RetChangeSmart(Item)
return '<DIV style="width: 204px;">' + Name + '<button onclick="ChangeSmart(' + Item.Num + ',' + Item.Value.Smart + ')" class="setsmart" style="height: ' + Height + 'px;min-height: ' + Height + 'px;">Set</button>' + State + '</DIV>';
};
function RetHistoryAccount(Item)
function RetHistoryAccount(Item,Name)
{
if(Item.Num < 16)
return "" + Item.Num;
return "<a class='olink' target='_blank' href='./history.html#" + Item.Num + "'>" + Item.Num + "</a>";
var Num;
if(Name)
Num = Item[Name];
else
Num = Item.Num;
if(Num < 16)
return "" + Num;
return "<a class='olink' target='_blank' href='./history.html#" + Num + "'>" + Num + "</a>";
};
function RetBaseAccount(Item)
{
var Str = "" + Item.Account;
var Str = RetHistoryAccount(Item, "Account");
if(Item.AccountLength > 1)
Str += "-" + (Item.Account + Item.AccountLength - 1);
return Str;
@ -972,7 +977,7 @@ function formatDate(now)
"0") + ":" + String(minute).padStart(2, "0") + ":" + String(second).padStart(2, "0");
};
function DateFromBlock(BlockNum,bAddEnter)
function DateFromBlock(BlockNum)
{
var Str;
if(window.FIRST_TIME_BLOCK)

View File

@ -12,6 +12,14 @@ var DiagramMap = {};
var DiagramMapId = {};
var LMouseOn = false;
function Rigth(Str,Count)
{
if(Str.length < Count)
return Str;
else
return Str.substr(Str.length - Count);
};
function SetHTMLDiagramItem(Item,width)
{
Item.mouseX = width - 50;
@ -87,11 +95,15 @@ function DrawDiagram(Item)
var arr = Item.arr;
if(!arr)
arr = Item.ArrList;
var arrX = Item.arrX;
var GreenValue = Item.value;
var StepTime = Item.steptime;
var StartNumber = Item.startnumber;
var StartServer = Item.starttime;
var mouseX = Item.mouseX;
var KPrecision = Item.KPrecision;
if(!KPrecision)
KPrecision = 1;
if(!arr)
return ;
var obj = document.getElementById(Item.id);
@ -166,6 +178,7 @@ function DrawDiagram(Item)
function DrawLines(arr,mode,color)
{
var WasMove0 = 0;
ctx.beginPath();
ctx.moveTo(Left, obj.height - Button);
ctx.strokeStyle = color;
@ -198,7 +211,15 @@ function DrawLines(arr,mode,color)
var x = StartX + ctx.lineWidth / 2 + (i) * KX;
if(bLine)
{
ctx.lineTo(x, StartY - VX2);
if(!WasMove0)
{
WasMove0 = 1;
ctx.moveTo(x, StartY - VX2);
}
else
{
ctx.lineTo(x, StartY - VX2);
}
}
else
{
@ -255,8 +276,8 @@ function DrawLines(arr,mode,color)
if(mouseValue !== undefined)
{
ctx.fillStyle = mouseColor;
var Str = "" + Math.floor(mouseValue + 0.5);
ctx.fillText(Str, mouseX - 3, Top - 2);
var Val = Math.floor(KPrecision * mouseValue + 0.5) / KPrecision;
ctx.fillText("" + Val, mouseX - 3, Top - 2);
}
}
ctx.fillStyle = "#000";
@ -285,28 +306,32 @@ function DrawLines(arr,mode,color)
var KDelitel = 1;
var Step = arr.length / CountNameX;
var StartTime, bNumber;
if(StartNumber !== undefined)
if(arrX)
{
bNumber = 1;
StartTime = StartNumber;
}
else
if(StartServer)
if(StartNumber !== undefined)
{
bNumber = 1;
StartTime = Math.floor(((Date.now() - StartServer) - StepTime * arr.length * 1000) / 1000);
if(StartTime < 0)
StartTime = 0;
var KDelitel = Math.floor(Step / 10) * 10;
if(KDelitel == 0)
KDelitel = 1;
StartTime = StartNumber;
}
else
{
bNumber = 0;
StartTime = Date.now() - StepTime * arr.length * 1000;
StartX = StartX - 16;
}
if(StartServer)
{
bNumber = 1;
StartTime = Math.floor(((Date.now() - StartServer) - StepTime * arr.length * 1000) / 1000);
if(StartTime < 0)
StartTime = 0;
var KDelitel = Math.floor(Step / 10) * 10;
if(KDelitel == 0)
KDelitel = 1;
}
else
{
bNumber = 0;
StartTime = Date.now() - StepTime * arr.length * 1000;
StartX = StartX - 16;
}
for(i = 0; i <= CountNameX; i++)
{
var Val;
@ -321,18 +346,26 @@ function DrawLines(arr,mode,color)
else
Val = i * Step * StepTime;
var Str;
if(bNumber)
if(arrX)
{
Val = Math.floor((StartTime + Val) / KDelitel) * KDelitel;
Str = Val;
Val = Math.floor(Val);
Str = arrX[Val];
if(Str === undefined)
Str = "";
}
else
{
var Time = new Date(StartTime + Val * 1000);
Str = "" + Time.getHours();
Str += ":" + Rigth("0" + Time.getMinutes(), 2);
Str += ":" + Rigth("0" + Time.getSeconds(), 2);
}
if(bNumber)
{
Val = Math.floor((StartTime + Val) / KDelitel) * KDelitel;
Str = Val;
}
else
{
var Time = new Date(StartTime + Val * 1000);
Str = "" + Time.getHours();
Str += ":" + Rigth("0" + Time.getMinutes(), 2);
Str += ":" + Rigth("0" + Time.getSeconds(), 2);
}
ctx.fillText(Str, StartX + i * KX3, StartY + 10);
}
};

View File

@ -304,8 +304,10 @@ function SendMoneyBefore()
var StrTo = " to " + GetAccountText(Item, ToID);
$("idWhiteOnSend").checked = 0;
$("idOnSendText").innerHTML = "<B style='color:#ff4534'>" + SumSend + "</B> " + $("idCoinName").innerText + StrTo;
if(SumSend >= 100000)
if($("idSumSend").value >= 100000)
{
$("idOnSendText").innerHTML += "<BR><DIV style='color: yellow;'>WARNING: You are about to send a very large amount!</DIV>";
}
SetVisibleBlock("idBlockOnSend", 1);
SetImg(this, 'idBlockOnSend');
}
@ -594,6 +596,19 @@ function OpenAttach()
alert("DATA:\n" + JSON.stringify(Data2, "", 4));
}
};
var CURRENCY, PUBKEY, NAME, SMART;
function SendTrCreateAccWait(Currency,PubKey,Name,Smart)
{
CURRENCY = Currency;
PUBKEY = PubKey;
NAME = Name;
SMART = Smart;
setTimeout(function ()
{
SendTrCreateAcc(CURRENCY, PUBKEY, NAME, 0, SMART, 0, 0);
}, 50);
};
function SendTrCreateAcc(Currency,PubKey,Description,Adviser,Smart,bFindAcc,bAddToPay)
{
@ -625,25 +640,47 @@ function ChangeSmart(NumAccount,WasSmart)
if(Result !== null && Result != WasSmart)
{
var Smart = parseInt(Result);
var OperationID = 0;
var Item = MapAccounts[NumAccount];
if(Item)
if(Smart)
{
OperationID = Item.Value.OperationID;
GetData("GetDappList", {StartNum:Smart, CountNum:1}, function (Data)
{
if(Data && Data.result && Data.arr.length === 1)
{
SetSmartToAccount(NumAccount, Smart);
}
else
{
SetError("Error smart number");
}
});
}
else
{
SetSmartToAccount(NumAccount, Smart);
}
OperationID++;
var TR = {Type:140, Account:NumAccount, Smart:Smart, FromNum:NumAccount, Reserve:[], OperationID:OperationID, Sign:"", };
var Body = [];
WriteByte(Body, TR.Type);
WriteUint(Body, TR.Account);
WriteUint32(Body, TR.Smart);
WriteArr(Body, TR.Reserve, 10);
WriteUint(Body, TR.FromNum);
WriteUint(Body, TR.OperationID);
SendTrArrayWithSign(Body, TR.Account, TR);
}
};
function SetSmartToAccount(NumAccount,Smart)
{
var OperationID = 0;
var Item = MapAccounts[NumAccount];
if(Item)
{
OperationID = Item.Value.OperationID;
}
OperationID++;
var TR = {Type:140, Account:NumAccount, Smart:Smart, FromNum:NumAccount, Reserve:[], OperationID:OperationID, Sign:"", };
var Body = [];
WriteByte(Body, TR.Type);
WriteUint(Body, TR.Account);
WriteUint32(Body, TR.Smart);
WriteArr(Body, TR.Reserve, 10);
WriteUint(Body, TR.FromNum);
WriteUint(Body, TR.OperationID);
SendTrArrayWithSign(Body, TR.Account, TR);
};
function CheckLengthAccDesription(name,Length)
{
var Str = $(name).value.substr(0, Length + 1);

View File

@ -226,7 +226,7 @@ function FindLider()
var Item = Arr[i];
if(Item.SumPower === MaxKey)
{
SetStatus("Find " + Item.ip + ":" + Item.port + " with pow=" + Item.SumPower + " " + Max + " ping=" + Item.DeltaTime);
SetStatus("Find " + Item.ip + ":" + Item.port + " with pow=" + Item.SumPower + "/" + MaxKey + " ping=" + Item.DeltaTime);
MainServer = Item;
SaveServerMap();
break;

View File

@ -528,7 +528,6 @@
{
var bDisabled=(CurProjectValue!=$("idProjectList").value);
var Arr=["idName","idShortName","idISIN","idCode","idHTML","idDescription","idTokenGenerate","idStartValue","idOwnerPubKey","idAccountLength","idStateFormat","idCategory1","idCategory2","idCategory3","idIcon","idBtIcon","idBtSendSmart"];
for(var i=0;i<Arr.length;i++)
{
@ -539,6 +538,9 @@
else
item.classList.remove("Disabled");
}
SetVisibleBlock("idRefHTML",bDisabled);
return !bDisabled;
}
@ -567,6 +569,14 @@
{
var Smart=SetData.arr[0];
LoadSmart("/file/"+Smart.BlockNum+"/"+Smart.TrNum);
var Str="";
if(Smart.BaseState && Smart.BaseState.HTMLBlock)
{
var Url="/file/"+Smart.BaseState.HTMLBlock+"/"+Smart.BaseState.HTMLTr;
Str="<a target='_blank' href='"+Url+"'>"+Url+"</a>";
}
$("idRefHTML").innerHTML=Str;
//SetSmartToDialog(Smart,1);
}
else
@ -610,11 +620,11 @@
function SetCurrentSmart()
{
CurProjectValue=undefined;
SetDialogEnabled();
var SmartValue=$("idSmartList").value;
if(SmartValue)
LoadSmart(SmartValue);
SetDialogEnabled();
}
function FillSmart()
{
@ -840,7 +850,7 @@
</DIV>
UI (HTML):
<DIV style="float: left;">UI (HTML):</DIV><DIV id="idRefHTML" style="float: left;">----</DIV>
<textarea rows="15" cols="98" id="idHTML" style="width: 99%;">
</textarea>
</DIV>

View File

@ -157,6 +157,8 @@
Data.WalletIsOpen=IsPrivateMode(localStorage["idPrivKey"]);
Data.WalletCanSign=Data.WalletIsOpen;
}
CONFIG_DATA.WalletCanSign=Data.WalletCanSign;
CONFIG_DATA.PubKey=Data.PubKey;
}
SendMessage(Data);
@ -397,31 +399,31 @@
}
var WasCheckInstall=0;
var idInstallApp=0;
function CheckInstall()
{
if(WasCheckInstall)
return;
setInterval(function ()
if(!idInstallApp)
idInstallApp=setInterval(RunCheckInstall,2000);
}
function RunCheckInstall()
{
if(CONFIG_DATA && CONFIG_DATA.ArrWallet && CONFIG_DATA.ArrWallet.length===0)
{
if(CONFIG_DATA && CONFIG_DATA.ArrWallet && CONFIG_DATA.ArrWallet.length===0)
var StrRef;
if(MainServer)
StrRef='<A class="btcreate" href="./web-wallet.html#TabAccounts">Accounts</A>';
else
{
WasCheckInstall=1;
var StrRef;
if(MainServer)
StrRef='<A href="./web-wallet.html#TabAccounts">ACCOUNTS</A>';
if(localStorage["BIGWALLET"])
StrRef='<A class="btcreate" href="/wallet.html#TabAccounts">Config</A>'
else
{
if(localStorage["BIGWALLET"])
StrRef='<A href="/wallet.html#TabAccounts">CONFIG</A>'
else
StrRef='<A href="/web-wallet.html#TabAccounts">ACCOUNTS</A>';
}
SetStatus('<DIV style="background-color: peachpuff;">For install this application goto '+StrRef+' tab, select your account, press "Set" and enter smart number: <B>'+SMART.Num+'</B><DIV>');
StrRef='<A class="btcreate" href="/web-wallet.html#TabAccounts">Accounts</A>';
}
},2000);
var Str='<DIV style="background-color: #c8ecff;">For install this app press: <button class="btcreate" onclick="InstallApp()">Create account</button> or goto '+StrRef+' tab and Set smart number <B>'+SMART.Num+'</B> to your account<DIV>';
SetStatus(Str);
}
}
//LIB
@ -472,8 +474,45 @@
SetStatus("<DIV style='color:red'><B>"+Str+"</B></DIV>");
}
function CreateNewWebKeys()
{
var arr = new Uint8Array(32);
window.crypto.getRandomValues(arr);
var PrivKey=GetHexFromArr(sha3(arr));
localStorage["idPrivKey"]=PrivKey;
localStorage["idPubKey"]=GetHexFromArr(SignLib.publicKeyCreate(PrivKey,1));
CONFIG_DATA.PubKey=localStorage["idPubKey"];
console.log("CreateNewWebKeys: "+CONFIG_DATA.PubKey);
}
function InstallApp()
{
if(!CONFIG_DATA.WalletCanSign)
{
if(localStorage["BIGWALLET"])
{
SetError("Pls, open wallet");
return;
}
CreateNewWebKeys();
}
SetStatus("Calculate Tx, wait pls ...");
//SendTrCreateAccWait(0,SMART.Name,SMART.Num);
//console.log("PubKey: "+CONFIG_DATA.PubKey);
var TR=GetTrCreateAcc(0,CONFIG_DATA.PubKey,SMART.Name,0,SMART.Num);
var Body=GetBodyCreateAcc(TR);
SendTransaction(Body,TR);
if(idInstallApp)
{
clearInterval(idInstallApp);
idInstallApp=setInterval(RunCheckInstall,30000);
}
}
@ -499,6 +538,17 @@
margin: 0;
background-color:white;
}
.btcreate
{
height:20px;
background-color: #347867;
color: white;
cursor: pointer;
border-radius: 3px;
padding: 2px;
text-decoration: none;
border: 1px solid gray;
}
</style>
</head>

View File

@ -154,7 +154,7 @@
{
var Str;
if(Item.Direct===Direct)
Str=RetHistoryAccount({Num:Item.CorrID});
Str=RetHistoryAccount(Item,"CorrID");
else
Str=AccountID;

View File

@ -1549,12 +1549,16 @@
<th id="Item.Description" class="code">Description</th>
<th id="(RetCategory(Item))" class="">Category</th>
<th id="RetBaseAccount(Item)" class="num">Base Account</th>
<th id="Item.Owner" class="num">Owner</th>
<th id="(RetBaseAccount(Item))" class="num">Base Account</th>
<th id="(RetHistoryAccount(Item,'Owner'))" class="num">Owner</th>
<th id="RetBool(Item.TokenGenerate)" class="bool">Token generate</th>
<!--<th id="Item.ISIN" class="num">ISIN</th>-->
<th id="(RetOpenBlock(Item.BlockNum,1))" class="num">Block Num</th>
<!--<th id="GetHexFromArr(Item.SumHash)" class="hash">SumHash</th>-->
</tr>
</table>
@ -1721,8 +1725,11 @@
<th id="Item.Num" class="num">Num</th>
<th id="(RetOpenBlock(Item.BlockNum,Item.TrDataLen))" class="num">Block</th>
<th id="(escapeHtml(DateFromBlock(Item.BlockNum,1)))" class="date">Date</th>
<th id="GetHexFromArr(Item.Hash)" class="code">Hash</th>
<th id="GetHexFromArr(Item.AccHash)" class="code">AccHash</th>
<th id="GetHexFromArr(Item.SumHash)" class="code">SumHash</th>
<th id="Item.AccountMax" class="num">AccountMax</th>
<th id="Item.SmartCount" class="num">SmartCount</th>
<th id="GetHexFromArr(Item.SmartHash)" class="code">SmartHash</th>
</tr>
</table>
<INPUT type="button" onclick="ViewPrev(DefHash)" class="btdoit bt" value="<< Prev">
@ -1809,8 +1816,7 @@
<DIV id="idBlockOnSend" style="display: none">
<DIV align="center">
Send <B id="idOnSendText"></B>
Send <B id="idOnSendText"></B><BR>
<button onclick="SendMoney2()" id="idBtOnSend" class="radius">Send</button>
<button onclick='SetVisibleBlock("idBlockOnSend",0);' class="radius">Cancel</button>

File diff suppressed because it is too large Load Diff

View File

@ -231,9 +231,9 @@
}
function SetVisibleItemsKeys(EditFlag)
function SetVisibleItemsKeys(EditFlag,bOpenEdit)
{
if(EditFlag)
if(bOpenEdit)
{
$("idPrivKeyEdit").value=$("idPrivKey").value;
}
@ -344,7 +344,7 @@
return;
}
SetStatus("Calculate Tx, wait pls ...");
SendTrCreateAccWait(Currency,Name,Smart);
SendTrCreateAccWait(Currency,$("idPubKey").value,Name,Smart);
}
SetVisibleBlock("idAccountEdit",0)
}
@ -353,17 +353,6 @@
SetVisibleBlock("idAccountEdit",0)
}
var CURRENCY,NAME,SMART;
function SendTrCreateAccWait(Currency,Name,Smart)
{
CURRENCY=Currency;
NAME=Name;
SMART=Smart;
setTimeout(function ()
{
SendTrCreateAcc(CURRENCY,$("idPubKey").value,NAME,0,SMART,0,0);
},50)
}
@ -836,7 +825,7 @@
<tr id="WalRow1">
<td>Wallet:</td>
<td><button id="idPrivKeyButton" onclick="OpenWallet()">Wallet opened: </button></td>
<td><button onclick="SetVisibleItemsKeys(1)" class="btkey bigs">Edit...</button></td>
<td><button onclick="SetVisibleItemsKeys(1,1)" class="btkey bigs">Edit...</button></td>
</tr>
<tr id="WalRow2" style="display: none">
<td>Private key:</td>
@ -988,7 +977,7 @@
<th id="Item.Description" class="code dappdesc">Description</th>
<th id="(RetCategory(Item))" class="">Category</th>
<th id="RetBaseAccount(Item)" class="num">Base Account</th>
<th id="(RetBaseAccount(Item))" class="num">Base Account</th>
<th id="Item.Owner" class="num">Owner</th>
<th id="RetBool(Item.TokenGenerate)" class="bool">Token generate</th>
<!--<th id="Item.ISIN" class="num">ISIN</th>-->

View File

@ -1,5 +1,7 @@
# TERA BLOG
If you have written something important about TERA on a worldwide important portal and you think that you deserve a reward, please contact us:
* Discord: https://discord.gg/CvwrbeG.
* Telegram: @PsyArcus.
If you have written something important about TERA and think you deserve a reward, please contact US:
* Discord: https://discord.gg/CvwrbeG
* Telegram: [@PsyArcus](https://web.telegram.org/#/im?p=@PsyArcus)
* See more about reward: [TERA CONTENT FUND](https://terafoundation.org/tera-content-fund.html)

View File

@ -0,0 +1,135 @@
v. 0.897
The API-2 is designed to make it easier to write third-party applications. Server-side cryptography and POW operations are performed. Therefore, it is not recommended for public access, because it is not protected from DDOS attacks. Use it if applications such as the exchange server are on the same private network.
v. 0.884
Will be enhanced the behavior of the constants COREY_WATCH_DOG. If you will be the number 2: "COREY_WATCH_DOG": 2, instead of an overload will just trim the blocks on the 5000, it will save time filling out the memory hashes. I. e. mining will practically go without interruption
v. 0.880
It contains API Protocol improvements for DApp.
v. 0.867
Made Protocol support light-wallet, fixed a bug in validate download chains.
The update is optional and can be skipped.
v. 0.811
If you set a constant:
"WATCHDOG_BADACCOUNT": 1
then "BAD ACCOUNT Has"error checking will be enabled. When accumulating them in the amount of 60, automatic cutting of the blockchain into 5000 blocks will be launched, which in theory leads to the removal of this error. But this is not accurate.
v. 0.783
Fix history and dapp event bugs.
v. 0.753
The update is partially completed:
1. Half of the nodes have completed the update
2. The second half performs the transaction overwrite procedure (it will take a long time). To speed up, you can download the DB folder from the torrent.
v. 0.727
Fix minor bugs.
v. 0.719
The update is desirable for the stability of the network, which consists of nodes from different regions of the world. The algorithm of correction of the current number of the current block-robust with respect to the time deviation.
v. 0.718
The consensus algorithm was returned to its original level (0.703). The experiments of the new consensus failed. I'll think.
Thanks for your patience
v. 0.703
Fix visual part of DApp.
Made less memory usage when you turn off the logging of statistics.
The update does not contain any changes in the blockchain communication Protocol and can be omitted.
v. 0.685
Update 685 contains two mining constants (on the CONFIG tab, the CONSTANTS button):
"COUNT_MINING_CPU": 0,
"SIZE_MINING_MEMORY": 0,
If set to COUNT_MINING_CPU that starts the specified number of processes of mining, you can set more or fewer than there are physical cores.
If the value SIZE_MINING_MEMORY is set, this value is distributed to all processes (the specified number is divided by the number of processes).
v. 0.672
Fixed a hash table calculation bug (OUR ACCOUNT).
From the number 10195000 the calculation of the block hash changes.
v. 0.671
The current update 0.671 contains an improved miner. The exchange Protocol has not changed. It is recommended only if you want to improve mining.
v. 0.666
Button added Auto-update to wallet (near button mining). If the update mode is turned off, but a new version is uploaded to the network, the button becomes orange and it is written in the title bar of the window via slash (Example: 0.661/663).
Added the ability to send money to any public address. In this case, a new account is created upon receipt. The first line of the payment purpose is used as the name. For the creation of the account will be charged a fee.
Added the possibility of unlimited creation of new accounts, but with a fee. Now the fee is 10 Tera, but as the rate of the Tera increases, it will decrease. The fee is paid to account 0. To do this, when creating a new account, use the "Add to Pay list"button. Clicking on it on the Send tab creates a payment transaction for 10 Tera with the order to create an account. It must be sent manually-by pressing the Send button.
Added smart contracts. More detail will be description will be here soon.
v. 0.555
Fix problem with pow process.
More hashrate.
v. 0.553
Fixed small bug with update version installation (previously installed always, even if auto-update is disabled).
With block number 7000000 introduced protection against DDOS attacks when creating new accounts. New accounts will be allowed to be created only in limited quantities. For an unlimited number in the future will be expanded standard transaction transfer of funds. We plan to add support for transferring money to the wallet address (public key) without specifying an account. In this case, a new account will be created automatically and a small fee will be charged for its creation (for DDOS protection). Ordinary transaction of transfer of funds stating the account will not require a fee.
v. 0.545
Full utilization of memory and CPU.
More hashrate.
v. 0.542
More memory optimization. More hashrate.
v. 0.501
Small bugs fix.
v. 0.517
A small change in security. For limited web access to the wallet, you can set the external ip address of the computer from which access is allowed in the constant "HTTP_IP_CONNECT".
Example:
"HTTP_IP_CONNECT": "111.222.220.230",
Note:
Access to the wallet via the local address 127.0.0.1 is always allowed.
v. 0.501
Small bugs fix.
v. 0.452
The power of the network is growing. Now its value 2^27.6 = 200Mh/s.
v. 0.450
Reduce traffic pushed.
v. 0.418
Candidate stable 2 pushed.
v. 0.366
Minor changes to the interface part update 366:
The utility section now has the following buttons:
1. Rewrite transactions
2. Truncate chain
3. Clear DataBase
The first two items require you to enter a parameter - the depth of the chain for processing in blocks starting from the current one. The last point - clears completely the database, without affecting the parameters of the wallet and server constants. Works the same as deleting the DATA / DB folder.
v. 0.214
For the network, it is very important that the time on all nodes is the same. Otherwise, the exchange of packets becomes impossible. With the help of special algorithms, it is synchronized automatically and the general direction is such that it is equal to the UTC time. If you are sure that your server has exact time synchronization, then you can disable automatic synchronization (but under your responsibility). This is done in constants, set the value: "AUTO_COORECT_TIME": 0
v. 0.171
The second version with spam protection is released. Available in auto-update mode.
v. 0.169
Ban list enable.
v. 0.169
Ban list enable.
v. 0.162
If you do not specify a password for the http remote access port, access is allowed only from the local address 127.0.0.1.
v. 0.156
Added automatic tracking of the processes involved in mining. If processes lose connection with the main process, they are destroyed.
v. 0.155
You can set http password during the program installation from command line, example: node set httpport:8080 password:123.

View File

@ -0,0 +1 @@
# TERA CHANGELOG

View File

@ -1,3 +1,4 @@
TERA is a platform for developing applications in a decentralized network. Programs can manage and transfer any digital values, including coins and tokens. This platform allows you to build a world economy without borders. The network is built on a highly reliable blockchain Protocol with PoW consensus.
It is our great pleasure to invite you to join us to mine TERA, a coin that offers solutions for issues of existing cryptocurrencies, namely centralization, transaction throughput, transaction speed, confirmation times, transaction fees and general usability and difficulty of integration into existing payment and financial systems.
We have managed to create a blockchain with 1 second block time, 8 seconds for full confirmation of transfer and zero fees. On top of that TERA blockchain is capable of throughput of 1000 transactions per second while retaining all praised blockchain features and bringing huge possibilities for further development and seamless integration with existing infrastructure as well as with new emerging technologies.

View File

@ -1 +1 @@
# ABOUT TERA BLOCKCHAIN
# ABOUT TERA PLATFORM

View File

@ -0,0 +1,19 @@
## UPDATES
* **v. 0.897:**
The API-2 is designed to make it easier to write third-party applications. Server-side cryptography and POW operations are performed. Therefore, it is not recommended for public access, because it is not protected from DDOS attacks. Use it if applications such as the exchange server are on the same private network.
* **v. 0.884:**
Will be enhanced the behavior of the constants COREY_WATCH_DOG. If you will be the number 2: "COREY_WATCH_DOG": 2, instead of an overload will just trim the blocks on the 5000, it will save time filling out the memory hashes. I. e. mining will practically go without interruption
* **v. 0.880:**
It contains API Protocol improvements for DApp.
* **v. 0.877:**
Today will be an update. The update improves work of DApp.
The update is optional — you can skip it.
* **v. 0.867:**
Made Protocol support light-wallet, fixed a bug in validate download chains.
The update is optional and can be skipped.
[Full Changelog...](/changelog.html)

View File

@ -1,3 +1,4 @@
## UPDATES
* **v. 0.897:**
The API-2 is designed to make it easier to write third-party applications. Server-side cryptography and POW operations are performed. Therefore, it is not recommended for public access, because it is not protected from DDOS attacks. Use it if applications such as the exchange server are on the same private network.
@ -13,4 +14,6 @@ The update is optional — you can skip it.
* **v. 0.867:**
Made Protocol support light-wallet, fixed a bug in validate download chains.
The update is optional and can be skipped.
The update is optional and can be skipped.
[Full Changelog...](/changelog.html)

View File

@ -0,0 +1,16 @@
## NEWS
**Local blockchain desynchronization detector test**
The test network begins the test of a new detector for determining the desynchronization of the blockchain from the main chain.
If the last 10 blocks are created by their own node, then their POW should not differ more than 10 times from the previous blocks, otherwise the forced synchronization of the blockchain with the network is started.
Settings can be changed-new constant added:
```
  "RESYNC_CONDITION": {
    "OWN_BLOCKS": 10,
    "K_POW": 10
  },
```

View File

@ -0,0 +1,7 @@
* [1. TERA Source Code](https://sourceforge.net/p/tera/code/ci/master/tree/)
* [2. TERA DApp PAPER (ENG)](https://docs.google.com/document/d/1PXVBbMKdpsAKPkO9UNB5B-LMwIDjylWoHvAAzzrXjvU/edit?usp=sharing)
* [3. TERA DApp PAPER (RUS)](https://docs.google.com/document/d/1SkD4yc_POaGRMJRC6yGkDfdJUuKbcyq3JpG0cBXeYGM/edit?usp=sharing/)
* [4. FAQ](https://docs.google.com/document/d/10yXAKxaU7YgrQnbdXu_L7WWovUoRtdJwo3tXXaGZGSQ/edit?usp=sharing/)
* [5. TERA API](https://sourceforge.net/p/tera/code/ci/master/tree/Doc/Eng/API.md)
* [6. TERA API-2 (for Exchanges)](https://gitlab.com/terafoundation/tera/blob/master/Doc/Eng/API2.md)

View File

@ -0,0 +1,7 @@

* [1. TERA on QBTC Exchange](https://www.qbtc.ink/trade?symbol=TERA_BTC)
* [2. TERA on Bitalong Exchange](https://www.bitalong.com/trade/index/market/tera_usdt/)
* [3. TERA on Bitmesh Exchange](https://bitmesh.com/exchange?market=btc_tera#/)
* [4. TERA on CHAOEX Exchange](https://chaoex-en-us.udesk.cn/hc/articles/83487)
* [5. TERA on CITEX Exchange](https://www.citex.co.kr/#/trade/2/37)
* [6. TERA Roadmap](/#roadmap)

View File

@ -0,0 +1,5 @@

* [1. TERA Mining Documentation](https://sourceforge.net/p/tera/code/ci/master/tree/README.md)
* [2. TERA HASH](https://docs.google.com/document/d/18DtASGhrbRwXCAkQR1hQG0lVdrStp4CgA-pd6hicwfo/edit?usp=sharing/)

View File

@ -0,0 +1,9 @@

* [1. TERA Website](https://terafoundation.org/)
* [2. TERA EXPLORER](https://terafoundation.org/explorer.html)
* [3. TERA WALLET](https://terafoundation.org/web-wallet.html)
* [4. TERA NETWORK MAP](https://terafoundation.org/map.html)
* [5. TERA WHITE PAPER (EN)](https://terafoundation.org/files/TERA_WP_EN.pdf)
* [6. TERA WHITE PAPER (RU)](https://terafoundation.org/files/TERA_WP_RU.pdf)
* [7. TERA WHITE PAPER (DE)](https://terafoundation.org/files/TERA_WP_DE.pdf)
* [8. TERA WHITE PAPER (CN)](https://sourceforge.net/p/tera/code/ci/master/tree/Doc/Chinese/WP_chinese.pdf?format=raw)

View File

@ -0,0 +1,9 @@

* [1. TERA ANN on BitcoinTalk](https://bitcointalk.org/index.php?topic=4573801.0)
* [2. TERA on Twitter](https://twitter.com/terafoundation)
* [3. TERA on Reddit](https://www.reddit.com/user/Terafoundation)
* [4. TERA on Discord](https://discord.gg/CvwrbeG)
* [5. TERA Telegram Chanel](https://web.telegram.org/#/im?p=@terafoundation)
* [6. TERA on QQ](https://jq.qq.com/?_wv=1027&k=58VsQxc)

View File

@ -0,0 +1,4 @@

* [FMessenger](http://freetimes.cc/fmessenger/)

View File

@ -1,125 +1,92 @@
1. SCOPE
These are the Terms of Use (hereinafter referred to as the “Terms”) of the TERA Foundation (hereinafter referred to as “TERA”, ”we” or “us”). These Terms apply to any access and use of TERA Hub, TERA Nano and TERA Commander (collectively referred to hereinafter as “TERA Wallets” or “TERA Wallet”), the TERA cryptographic token (hereinafter referred to as “TERA”), the TERA website at https://www.terafoundation.org/, the online services, and any TERAs services related to or utilizing any of the foregoing which we refer to in these Terms, collectively, as “Services”, “TERA Services” or “our Services”.
2. ELIGIBILITY AND AGREEMENT
You must ensure that you use and access TERA Services only in your own name. If you are acting for a legal entity, you must ensure that you:
(a) use and access TERA Services on behalf of the legal entity; and
(b) that you are authorised to enter into transactions on behalf of the legal entity.
3. YOUR RESPONSIBILITIES REGARDING THE USE OF THE SERVICES
You are also responsible for maintaining adequate security, control and confidentiality of your device access, your TERA Wallets information, including passwords, passphrases, private keys or other codes associated with your TERA Wallets and any activity occurring within these TERA Wallets. The loss or compromise of this information may result in unauthorized access of your TERA Wallets, and loss or theft of any TERA and other cryptographic tokens held in your TERA Wallets.
If you believe your TERA Wallets have been compromised, or you need to report a security incident, or you have experienced any operational problems, or have a security concern, please contact us immediately at help@terafoundation.org describing the issue at hand as thoroughly as possible including the date, type of problem and part of the TERA site or TERA Services where you experienced that problem. You are responsible for (i) immediately notifying us of any unauthorized use of your password or TERA Wallets or any other breach of security, and (ii) ensuring that you log out from your TERA Wallets at the end of each session when accessing the TERA Services.
We have no responsibility for any loss that you suffer as a result of failing to comply with this section or failure to follow or act on any notices or alerts that we may send to you.
4. AVAILABILITY OF SERVICES
Subject to these Terms, TERA shall use reasonable efforts to make available, operate and maintain the TERA Services during the term of these Terms and to permit you to access and use the TERA Services in accordance with these Terms. TERA shall use all reasonable efforts to promptly notify you of any difficulties experienced by us or other participants with respect to their access to or the use of the TERA Services, but only to the extent that TERA is aware of such difficulties and reasonably determines that they are material to your access and use of the TERA Services. Similarly, you shall notify TERA the soonest possible in case you become aware of any material technical failures of or difficulties with the TERA Services or upon becoming aware of any material breach (or any event which, by giving notice and/or the lapse of time, would constitute a material breach) of these Terms.
Our Services may evolve over time. This means we may apply changes, replace, or discontinue (temporarily or permanently) our Services at any time for any reasonable cause with two days notice or without notice in case of a Force Majeure. In this case, you may be prevented from accessing or using our Services. If, in our sole discretion, we decide to permanently discontinue our Services, we will provide you with a notice via our website, via our Twitter account or any other means of communication we deem appropriate.
You accept and acknowledge that the TERA Services may not be accessible in every country of your residence, in particular because of regulatory requirements.
5. FORCE MAJEURE
A Force Majeure Event includes without limitation each of the following:
a) Government actions, the outbreak of war or hostilities, the threat of war, acts of terrorism, national emergency, riot, civil disturbance, sabotage, requisition, or any other international calamity, economic or political crisis;
b) Act of God, earthquake, tsunami, hurricane, typhoon, accident, storm, flood, fire, epidemic or other natural disaster;
c) Labour disputes and lock-out;
d) Breakdown, failure or malfunction of any electronic, network and communication lines or systems (not due to the fault of TERA);
e) Any event, act or circumstances not reasonably within TERAs control and the effect of that event(s) is such that TERA is not in a position to take any reasonable action to cure the default.
6. RISKS
You understand and accept the risks in connection with the use of the TERA Wallet app and using the Services as set forth above and hereinafter. In particular, but not limited to, you understand the inherent risks listed hereinafter:
a) Risk of software weaknesses: You understand and accept that the underlying software application and software platform is still in an early development stage and unproven, why there is no warranty that the Services will be uninterrupted or error-free and why there is an inherent risk that the software could contain weaknesses, vulnerabilities or bugs causing, inter alia, the complete loss of TERA.
b) Regulatory risk: You understand and accept that blockchain technology allows new forms of interaction and that it is possible that certain jurisdictions will apply existing regulations on, or introduce new regulations addressing, blockchain technology based applications, which may be contrary to the current setup of TERA and which may, inter alia, result in substantial modifications of the TERA Services, including its termination.
c) Risk of loss of private key or passphrase(s): TERA Wallet can only be accessed by using a TERA Wallet passphrase with the possibility of using a second passphrase. You understand and accept that if your private key, passphrase or second passphrase respectively got lost or stolen, the TERA within your TERA Wallet will be unrecoverable and will be permanently lost.
d) Risk of voting attacks: You understand and accept that the blockchain used for by TERA is susceptible to voting attacks, including but not limited to majority voting power attacks, “selfish-voting” attacks, and race condition attacks. Any successful attacks present a risk to the TERA Services.
e) Risk of delegate attacks: You understand and accept that the blockchain used for by TERA is susceptible to delegate attacks, including but not limited to double-spending attacks, majority delegate attacks, and race condition attacks. Any successful attacks present a risk to the TERA Services.
7. PUBLIC AND PRIVATE KEY, PASSPHRASES
When you create a TERA Wallet, the Services generate a digital private and public key pair and a passphrase. The Services never store either private key or passphrase. The public key generated by the Services is being used to generate a TERA Wallet address, and may be shared with the network and with others to complete transactions. The private key is associated to a TERA Wallet address and must be used in conjunction with the TERA Wallet address to authorize transactions from or to that TERA address.
You need to make sure that your passphrase(s) are properly backed up and protected from theft.
8. DATA PROTECTION
The information provided pursuant to these Terms will be used by TERA for the purposes of providing you with services and data pursuant to these Terms and enabling TERA to perform its activities.
You acknowledge and agree that TERA may disclose your data, including personal data and sensitive personal data as defined under the Swiss Federal Data Protection Act (“Participant Data”) to outside organisations for the purpose of providing services and data to you, and performing its activities. You explicitly consent to the export of your data to a location outside your country of domicile and to third parties outside of TERA.
9. PROHIBITED ACTIVITIES
You agree that you will not use the TERA Services to perform any type or sort of illegal activity or to take any action that negatively affects the performances of the TERA Services. You may not engage via the Services in any of the following activities, nor help a third party in any such activity to:
1) attempt to gain unauthorized access to our Services or another users TERA Wallet;
2) make any attempt to bypass or circumvent any security features;
3) violate any law, statute, ordinance, regulation or these Terms and other contractual documents as referred to herein;
4) reproduce, duplicate, copy, sell or resell our Services for any purpose except as authorized in these Terms;
10. DEFAULT
Each of the following constitutes an “Event of Default”:
a) Where any representation or warranty made by you is or becomes untrue;
b) Any other circumstance where TERA reasonably believes that it is necessary or desirable to take any action set out in the below paragraph;
c) You are performing a prohibited activity as specified in section 9, you involve TERA in any type of fraud or illegality and if TERA suspects that you are engaged into money laundering activities or terrorist financing or other criminal activities;
d) Commencement of proceedings or investigations against you by a governmental authority, including but not limited to the request for an action set out in the below paragraph by a competent governmental authority or body or court;
e) In cases of material violation by you of the requirements established by any applicable laws, such materiality determined in good faith by TERA;
f) Any other situation where it would not be in the best interest of TERA that you continue to be a participant.
If an Event of Default occurs, TERA may at its absolute discretion, at any time and without prior notice, take one or more of the following actions:
a) Terminate these Terms without notice;
b) Close any or all of your TERA Wallets;
c) Refuse to open a new TERA Wallet for you.
11. INDEMNIFICATION
You agree to indemnify, defend and hold TERA, its employees, agents, consultants, subsidiaries, partners, affiliates, and licensors, harmless against any and all claims, costs, losses, damages, liabilities, judgments and expenses (including reasonable fees of attorneys and other professionals) arising from or in any way related to your use of our Services, your violation of these Terms, or your violation of any rights of any other person or entity.
12. LIMITATION OF LIABILITY
To the extent permitted by applicable law, TERA and its auxiliary persons shall not be liable for any damage arising out of, or in connection with, this agreement.
TERA shall assume no liability for any further claims, e.g. relating to compensation for indirect or consequential loss, lost profit or loss of earnings, unrealised savings or additional expense incurred, regardless of the legal grounds.
You are fully aware that the access to and the use of the TERA Services through the internet, the TERA Wallets and from abroad might violate foreign laws applicable to you. You undertake to inform yourself and to assume sole liability for any risks relating to such foreign legislation. Any responsibility of TERA regarding the possible infringement of foreign laws in connection with your use of the Services from abroad is expressly and completely excluded.
TERA shall assume no liability for losses if, for reasons for which TERA cannot be held responsible, TERA has been prevented from performing the transaction properly or on time, for example as a result of Force Majeure or measures, orders and/or decrees issued by domestic or foreign governmental authorities.
In particular, TERA shall assume no liability for actions (e.g. declarations of Default), failure to take action or any suspension or restriction of services by any element within the blockchain. Furthermore, TERA shall assume no liability for the consequences of regulatory measures implemented by competent regulators with regard to any of the TERA Services.
13. TERMINATION
TERA reserves the right to close a TERA Wallet without prior notice immediately on the grounds of misusage particularly violations of these Terms or any applicable law.
14. TAXATION
You bear the sole responsibility to determine if your use of the Services and/or any other action or transaction related to TERA have tax implications for you.
By using the Services, and to the extent permitted by law, you agree not to hold TERA liable for any tax liability associated with or arising from the operation of the Services or any other action or transaction related to TERA Services.
15. ENTIRE AGREEMENT
These Terms, together with any other agreements that apply to you constitute the entire and exclusive agreement between us and you regarding its subject matter, and supersede and replace any previous or contemporaneous written or oral contract, warranty, representation or understanding regarding its subject matter.
16. SEVERABILITY
If for any reason a court of competent jurisdiction finds any provision of these Terms invalid or unenforceable or illegal or contravene any rule, regulation or law of any market or regulator, that part will be deemed to have been excluded from these Terms from the beginning, and these Terms will be interpreted and enforced as though the provision had never been included and the legality or enforceability of the remaining provisions of the Terms or the legality, validity or enforceability of this provision in accordance with the law and/or regulation of any other jurisdiction, shall not be affected but should remain in full force and effect.
17. CHANGES TO THESE TERMS
The present Terms may change from time to time, including but not limited to cases of changes in our Services, in technology, in regulation and for any other case that TERA deems as appropriate to take measures. In case of a change, we will provide you with notice of such change by posting the updated Terms on our website and changing the "Last Updated" date at the bottom of these Terms. Any amended Terms shall become effective not earlier than 14 days after they are posted and shall apply prospectively to the use of the Services upon effectiveness of such changes. However, in case the changes address new functions of TERA Services or they are made for any legal reasons, they shall be of immediate effect. Upon effectiveness of the change as described above, the change of Terms shall be considered as accepted by you in case you continue using the TERA Services. Therefore, in case you do not agree to any amended Term, you must immediately cease using the TERA Services.
18. COMPLAINTS AND DISPUTES
In the event that an alleged breach, controversy, claim, dispute or difference (a Dispute) arises between you and TERA out of or in connection with these Terms and any other contractual documents (including but not limited to the validity, performance, breach or termination thereof), the parties shall seek to resolve the matter by negotiation by referring the matter first to:
a) any member of your executive management in case of legal persons, or you personally if you are acting as a natural person;
b) in the case of TERA, to the TERA Help Center.
The following information will need to be included:
a) your name and surname;
b) your e-mail address (or other recognition details);
c) detailed enquiry description;
e) the date and time that the issue arose.
The Help Center shall:
* send an official response to you within 14 business days respectively;
* try to resolve the matter as soon as reasonably possible;
* inform you of the outcome.
20. DISPUTE RESOLUTION, PLACE OF JURISDICTION AND GOVERNING LAW
These Terms and any other applicable contractual documents shall exclusively be governed by and construed in accordance with the substantive laws of Switzerland, excluding the conflict of laws principles thereof.
1. SCOPE
These are the Terms of Use (hereinafter referred to as the “Terms”) of the TERA Foundation (hereinafter referred to as “TERA”, ”we” or “us”). These Terms apply to any access and use of TERA DEX, TERA DApp and TERA Wallet, the TERA cryptographic coin (hereinafter referred to as “TERA”), the TERA website at https://www.terafoundation.org/, the online services, and any TERAs services related to or utilizing any of the foregoing which we refer to in these Terms, collectively, as “Services”, “TERA Services” or “our Services”.
2. ELIGIBILITY AND AGREEMENT
You must ensure that you use and access TERA Services only in your own name. If you are acting for a legal entity, you must ensure that you:
(a) use and access TERA Services on behalf of the legal entity; and
(b) that you are authorised to enter into transactions on behalf of the legal entity.
3. YOUR RESPONSIBILITIES REGARDING THE USE OF THE SERVICES
You are also responsible for maintaining adequate security, control and confidentiality of your device access, your TERA Wallets information, including passwords, passphrases, private keys or other codes associated with your TERA Wallets and any activity occurring within these TERA Wallets. The loss or compromise of this information may result in unauthorized access of your TERA Wallets, and loss or theft of any TERA and other cryptographic tokens held in your TERA Wallets.
If you believe your TERA Wallets have been compromised, or you need to report a security incident, or you have experienced any operational problems, or have a security concern, please contact us immediately at help@terafoundation.org describing the issue at hand as thoroughly as possible including the date, type of problem and part of the TERA site or TERA Services where you experienced that problem. You are responsible for (i) immediately notifying us of any unauthorized use of your password or TERA Wallets or any other breach of security, and (ii) ensuring that you log out from your TERA Wallets at the end of each session when accessing the TERA Services.
We have no responsibility for any loss that you suffer as a result of failing to comply with this section or failure to follow or act on any notices or alerts that we may send to you.
4. AVAILABILITY OF SERVICES
Subject to these Terms, TERA shall use reasonable efforts to make available, operate and maintain the TERA Services during the term of these Terms and to permit you to access and use the TERA Services in accordance with these Terms. TERA shall use all reasonable efforts to promptly notify you of any difficulties experienced by us or other participants with respect to their access to or the use of the TERA Services, but only to the extent that TERA is aware of such difficulties and reasonably determines that they are material to your access and use of the TERA Services. Similarly, you shall notify TERA the soonest possible in case you become aware of any material technical failures of or difficulties with the TERA Services or upon becoming aware of any material breach (or any event which, by giving notice and/or the lapse of time, would constitute a material breach) of these Terms.
Our Services may evolve over time. This means we may apply changes, replace, or discontinue (temporarily or permanently) our Services at any time for any reasonable cause with two days notice or without notice in case of a Force Majeure. In this case, you may be prevented from accessing or using our Services. If, in our sole discretion, we decide to permanently discontinue our Services, we will provide you with a notice via our website, via our Twitter account or any other means of communication we deem appropriate.
You accept and acknowledge that the TERA Services may not be accessible in every country of your residence, in particular because of regulatory requirements.
5. FORCE MAJEURE
A Force Majeure Event includes without limitation each of the following:
a) Government actions, the outbreak of war or hostilities, the threat of war, acts of terrorism, national emergency, riot, civil disturbance, sabotage, requisition, or any other international calamity, economic or political crisis;
b) Act of God, earthquake, tsunami, hurricane, typhoon, accident, storm, flood, fire, epidemic or other natural disaster;
c) Labour disputes and lock-out;
d) Breakdown, failure or malfunction of any electronic, network and communication lines or systems (not due to the fault of TERA);
e) Any event, act or circumstances not reasonably within TERAs control and the effect of that event(s) is such that TERA is not in a position to take any reasonable action to cure the default.
6. RISKS
You understand and accept the risks in connection with the use of the TERA Wallet app and using the Services as set forth above and hereinafter. In particular, but not limited to, you understand the inherent risks listed hereinafter:
a) Risk of software weaknesses: You understand and accept that the underlying software application and software platform is still in an early development stage and unproven, why there is no warranty that the Services will be uninterrupted or error-free and why there is an inherent risk that the software could contain weaknesses, vulnerabilities or bugs causing, inter alia, the complete loss of TERA.
b) Regulatory risk: You understand and accept that blockchain technology allows new forms of interaction and that it is possible that certain jurisdictions will apply existing regulations on, or introduce new regulations addressing, blockchain technology based applications, which may be contrary to the current setup of TERA and which may, inter alia, result in substantial modifications of the TERA Services, including its termination.
c) Risk of loss of private key or passphrase(s): TERA Wallet can only be accessed by using a TERA Wallet passphrase with the possibility of using a second passphrase. You understand and accept that if your private key, passphrase or second passphrase respectively got lost or stolen, the TERA within your TERA Wallet will be unrecoverable and will be permanently lost.
d) Risk of voting attacks: You understand and accept that the blockchain used for by TERA is susceptible to voting attacks, including but not limited to majority voting power attacks, “selfish-voting” attacks, and race condition attacks. Any successful attacks present a risk to the TERA Services.
e) Risk of delegate attacks: You understand and accept that the blockchain used for by TERA is susceptible to delegate attacks, including but not limited to double-spending attacks, majority delegate attacks, and race condition attacks. Any successful attacks present a risk to the TERA Services.
7. PUBLIC AND PRIVATE KEY, PASSPHRASES
When you create a TERA Wallet, the Services generate a digital private and public key pair and a passphrase. The Services never store either private key or passphrase. The public key generated by the Services is being used to generate a TERA Wallet address, and may be shared with the network and with others to complete transactions. The private key is associated to a TERA Wallet address and must be used in conjunction with the TERA Wallet address to authorize transactions from or to that TERA address.
You need to make sure that your passphrase(s) are properly backed up and protected from theft.
8. DATA PROTECTION
The information provided pursuant to these Terms will be used by TERA for the purposes of providing you with services and data pursuant to these Terms and enabling TERA to perform its activities.
You acknowledge and agree that TERA may disclose your data, including personal data and sensitive personal data as defined under the Swiss Federal Data Protection Act (“Participant Data”) to outside organisations for the purpose of providing services and data to you, and performing its activities. You explicitly consent to the export of your data to a location outside your country of domicile and to third parties outside of TERA.
9. PROHIBITED ACTIVITIES
You agree that you will not use the TERA Services to perform any type or sort of illegal activity or to take any action that negatively affects the performances of the TERA Services. You may not engage via the Services in any of the following activities, nor help a third party in any such activity to:
1) attempt to gain unauthorized access to our Services or another users TERA Wallet;
2) make any attempt to bypass or circumvent any security features;
3) violate any law, statute, ordinance, regulation or these Terms and other contractual documents as referred to herein;
4) reproduce, duplicate, copy, sell or resell our Services for any purpose except as authorized in these Terms;
10. DEFAULT
Each of the following constitutes an “Event of Default”:
a) Where any representation or warranty made by you is or becomes untrue;
b) Any other circumstance where TERA reasonably believes that it is necessary or desirable to take any action set out in the below paragraph;
c) You are performing a prohibited activity as specified in section 9, you involve TERA in any type of fraud or illegality and if TERA suspects that you are engaged into money laundering activities or terrorist financing or other criminal activities;
d) Commencement of proceedings or investigations against you by a governmental authority, including but not limited to the request for an action set out in the below paragraph by a competent governmental authority or body or court;
e) In cases of material violation by you of the requirements established by any applicable laws, such materiality determined in good faith by TERA;
f) Any other situation where it would not be in the best interest of TERA that you continue to be a participant.
If an Event of Default occurs, TERA may at its absolute discretion, at any time and without prior notice, take one or more of the following actions:
a) Terminate these Terms without notice;
b) Close any or all of your TERA Wallets;
c) Refuse to open a new TERA Wallet for you.

View File

@ -1 +1 @@
# ABOUT TERA TOKEN
# ABOUT TERA COIN

View File

@ -1,6 +1,9 @@
function setCookie(name,value,days) {
function setCookie(name,value)
{
var days=365;
var expires = "";
if (days) {
if (days)
{
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
@ -8,7 +11,8 @@ function setCookie(name,value,days) {
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
function getCookie(name)
{
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
@ -19,11 +23,13 @@ function getCookie(name) {
return null;
}
function eraseCookie(name) {
function eraseCookie(name)
{
document.cookie = name+'=; Max-Age=-99999999;';
}
var show = getCookie('teracookies');
if (!show) {
if (!show)
{
setTimeout("document.getElementById('cookiesmessage').style.display = 'block';", 3000);
}
}

View File

@ -38,6 +38,9 @@
//запрос исходного содержания файла
//отображение кнопки записи и отмены (прячем кнопку редактирования)
if(PrevEditContent[Name])
return;
var elem=ByID(Name);
PrevEditContent[Name]=elem.innerHTML;
var Path=EditMap[Name];

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -21,30 +21,8 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="../CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
{{File=./SITE/metrika.html}}
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -1,7 +1,7 @@
<ul class="main-nav nav navbar-nav navbar-right white_menu">
<li><a href="/#about">ABOUT</a></li>
<!--li><a href="/changelog.html">CHANGELOG</a></li-->
<li><a href="/tera-token.html">TERA TOKEN</a></li>
<li><a href="/tera-token.html">TERA COIN</a></li>
<li><a href="/blog/">BLOG</a></li>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="../CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -51,30 +51,9 @@
}
</style>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -51,30 +51,9 @@
}
</style>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -8,7 +8,7 @@
<meta data-n-head="true" data-hid="description" name="description" content="Tera - Fast block generation, High transaction throughput, User-friendly">
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
<title>TERA Foundation: TOKEN</title>
<title>TERA Foundation: COIN</title>
<!-- Google font -->
<link href="https://fonts.googleapis.com/css?family=Montserrat:400,700%7CVarela+Round" rel="stylesheet">
@ -51,30 +51,9 @@
}
</style>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -51,30 +51,9 @@
}
</style>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>
@ -112,7 +91,7 @@
<ul class="main-nav nav navbar-nav navbar-right white_menu">
<li><a href="#about">ÜBER TERA</a></li>
<!--li><a href="/changelog.html" target="_blank">CHANGELISTE</a></li-->
<li><a href="/tera-token.html" target="_blank">TERA TOKEN</a></li>
<li><a href="/tera-token.html" target="_blank">TERA COIN</a></li>
<li><a href="/blog/" target="_blank">BLOG</a></li>

256
Source/SITE/emission.html Normal file
View File

@ -0,0 +1,256 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Tera Emission</title>
<script type="text/javascript" src="../HTML/JS/diagram.js"></script>
<script>
function UpdateDiagrams()
{
// var Account0=529202650;
// var BlockNumStart=22841472;
var Account0=Math.floor($("idAccount0Start").value);
var BlockNumStart=Math.floor($("idBlockNumStart").value);
var BlockNumEnd=Math.floor($("idBlockNumEnd").value);
var KTera=Number($("idKTera").value);
var PERIOD_END_43=Math.floor($("idPERIOD_END_43").value);
var PERIOD_END_45=Math.floor($("idPERIOD_END_45").value);
var StepNumber=24*3600;
var Ret=CalcReward(Account0,BlockNumStart,BlockNumEnd,StepNumber,KTera,PERIOD_END_43,PERIOD_END_45);
var ArrX=[];
for(var i=0;i<Ret.BlockNum.length;i++)
ArrX[i]=DateFromBlock(Ret.BlockNum[i]);
var MaxEmission=1000;
var ArrEmission=[];
for(var i=0;i<Ret.Account0.length;i++)
{
if(i<365)
{
if(i>=1)
{
ArrEmission[i]=365*(Ret.Account0[0]-Ret.Account0[i])/i;
if(i===1)
ArrEmission[0]=ArrEmission[i];
}
else
{
ArrEmission[i]=0;
}
}
else
{
ArrEmission[i]=Ret.Account0[i-365]-Ret.Account0[i];
}
}
DrawDiagramMy({id:"idReward",red:"#1b9031",arrX:ArrX,arr:Ret.Reward,KPrecision:100});
DrawDiagramMy({id:"idEmission",red:"#c0465d",arrX:ArrX,arr:ArrEmission,KPrecision:10});
DrawDiagramMy({id:"idAccount0",red:"#1e21cb",startnumber:BlockNumStart,steptime:StepNumber,arr:Ret.Account0});
}
function DrawDiagramMy(Item)
{
Item.name=Item.id;
Item.fillStyle="#FFF";
Item.line=1;
if(!Item.steptime)
Item.steptime=1;
DiagramMapId[Item.id]=Item;
DiagramMap[Item.name]=Item;
DrawDiagram(Item);
}
window.onload=function()
{
//COMMON MOUSE MOVING
window.onmousemove = function(event)
{
SetDiagramMouseX(event);
}
//UpdateDiagrams();
InitDiagramByArr([]);
};
function $(id)
{
return document.getElementById(id);
}
</script>
<script>
function CalcReward(Account0,BlockNumStart,BlockNumEnd, ArrDelta, KTera, PERIOD_END_43,PERIOD_END_45)
{
//old consts
var REF_PERIOD_START=2*1000000;
var REF_PERIOD_END=30*1000000;
// var PERIOD_END_43=43*1000000;
// var PERIOD_END_45=45*1000000;
var ArrIndex=0;
var Ret={Reward:[],Account0:[],Emission:[],BlockNum:[]};
var BlockNum=BlockNumStart;
//var KTera=3;
var SumReward=0;
var NumDelta=0;
while(BlockNum<=BlockNumEnd)
{
var Reward=Account0*43*43/100/1000000000;
if(BlockNum<=REF_PERIOD_END)
{
Reward=Account0*43*43/100/1000000000;
var K=(REF_PERIOD_END-BlockNum)/(REF_PERIOD_END-REF_PERIOD_START);
if(K>0)
Reward+=2*K*Reward;
}
else
if(BlockNum<=PERIOD_END_43)
{
Reward=Account0*43*43/100/1000000000;
var K=(PERIOD_END_45-BlockNum)/(PERIOD_END_45-REF_PERIOD_END);
Reward=K*Reward
}
else
{
Reward=KTera*Account0/1000000000;
}
SumReward=SumReward+Reward;
Account0-=Reward;
//stat
NumDelta++;
if(NumDelta>=ArrDelta)
{
Ret.Reward[ArrIndex]=Reward;
Ret.Account0[ArrIndex]=Account0/1000000;
//Ret.Emission[ArrIndex]=SumReward/1000000;
Ret.BlockNum[ArrIndex]=BlockNum;
ArrIndex++;
//console.log(""+DateFromBlock(BlockNum)+" = "+Reward+" SUM:"+Math.floor(SumReward)+"/"+Math.floor(Account0));
NumDelta=0;
SumReward=0;
}
BlockNum++;
}
return Ret;
}
function formatDate(now)
{
var year=now.getFullYear();
var month=now.getMonth()+1;
var date=now.getDate();
return year+"-"+String(month).padStart(2,"0")+"-"+String(date).padStart(2,"0");
}
function DateFromBlock(BlockNum)
{
var Str;
var FIRST_TIME_BLOCK=1530446400000;
var now = new Date(FIRST_TIME_BLOCK + BlockNum * 1000);
Str = formatDate(now);
return Str;
};
</script>
</head>
<body>
<h3>The parameters of the economy</h3>
<TABLE>
<TR>
<TD>
Point 43:
</TD>
<TD>
<INPUT type="number" id="idPERIOD_END_43" style="width:120px" value="43000000">
</TD>
</TR>
<TR>
<TD>
Point 45:
</TD>
<TD>
<INPUT type="number" id="idPERIOD_END_45" style="width:120px" value="45500000">
</TD>
</TR>
<TR>
<TD>
KTera:
</TD>
<TD>
<INPUT type="number" id="idKTera" style="width:120px" value="3">
</TD>
</TR>
</TABLE>
<h3>The parameters of view</h3>
<TABLE>
<TR>
<TD>
Start BlockNum:
</TD>
<TD>
<INPUT type="number" id="idBlockNumStart" style="width:120px" value="22841472">
</TD>
</TR>
<TR>
<TD>
Start Account0:
</TD>
<TD>
<INPUT type="number" id="idAccount0Start" style="width:120px" value="529202650">
</TD>
</TR>
<TR>
<TD>
End BlockNum:
</TD>
<TD>
<INPUT type="number" id="idBlockNumEnd" style="width:120px" value="100000000">
</TD>
</TR>
<TR>
<TD>
<button onclick="UpdateDiagrams()">SHOW DIAGRAMS</button>
</TD>
</TR>
</TABLE>
<h4 >Reward, TERA per block</h4>
<canvas class="DIAGRAM" width='1100' height='200' id='idReward'></canvas>
<h4 >Emission, Million TERA per Year</h4>
<canvas class="DIAGRAM" width='1100' height='200' id='idEmission'></canvas>
<h4 >Balance of account 0, Million TERA</h4>
<canvas class="DIAGRAM" width='1100' height='200' id='idAccount0'></canvas>
</body>
</html>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>
@ -286,10 +265,10 @@ We will create a roadmap in more detail in the near future.
<hr />
<p>
<strong><span class="faqa">Will it take one common IP address per node in the future?
<strong><span class="faqa">Will it take one public IP address per node in the future?
</span></strong>
<p>Yes.
<p>Yes. TERA is not just a decentralized network - it is a distributed network. So we need to have a lot of public addresses.
</p>
@ -304,4 +283,4 @@ We will create a roadmap in more detail in the near future.
</div>
<!-- /About Tera -->
{{File=./SITE/footer_index.html}}
{{File=./SITE/footer_index.html}}

View File

@ -41,10 +41,11 @@
<p align="center">
Project Founder Email: <a href="mailto: progr76@gmail.com" style="font-size: 14px;">progr76@gmail.com</a>.
</p>
<p align="center">
<a href="terms-and-conditions.html">Terms and Conditions</a> | <a href="privacy-policy.html">Privacy Policy</a><br /><br />TERA Foundation, 2018 — 2019.
<p align="center">
<a href="terms-and-conditions.html">Terms and Conditions</a> | <a href="privacy-policy.html">Privacy Policy</a> | <a href="/admin" style="font-size: 14px;">admin</a> | <a href="/blog/reload" style="font-size: 14px;">reload</a><br /><br />TERA Foundation, 2017 — 2019.
</p>
</div>
</div>
</div>
<!-- /Row -->
</div>
@ -65,4 +66,4 @@
</body>
</html>
</html>

View File

@ -18,31 +18,9 @@
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
{{File=./SITE/metrika.html}}
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>
@ -78,7 +56,7 @@
<ul class="main-nav nav navbar-nav navbar-right white_menu">
<li><a href="#about">ABOUT</a></li>
<!--li><a href="/changelog.html">CHANGELOG</a></li-->
<li><a href="/tera-token.html">TERA TOKEN</a></li>
<li><a href="/tera-token.html">TERA COIN</a></li>
<li><a href="/blog/">BLOG</a></li>

View File

@ -11,7 +11,7 @@
{{Edit=./SITE/CONTENT/en-index-about-title.md}}
</div>
<p class="tera-logo-panel">
<img src="PIC/Tera_Logo.png" width="240" />
<img src="PIC/map-nodes.jpg" width="623" height="332"/>
</p>
{{Edit=./SITE/CONTENT/en-index-about-text.md}}
<p class="tera-logo-panel">
@ -113,51 +113,6 @@
<!-- /Container -->
</div>
<div id="lastnews" class="section md-padding bg-grey">
<!-- Container -->
<div class="container">
<!-- Row -->
<div class="row">
<!-- Section header -->
<div class="section-header">
<h2>Latest News</h2>
</div>
<div class="col-md-4">
<div class="about bg-grey last-news-panel">
<img src="/blog/uploads/1/1_1.png" alt="Rewarding authors of articles for the TERA Content Fund" />
<p>11-March-2019</p>
<a href="/blog/5-rewarding-authors-of-articles-for-the-tera-fontent-fund.html">Rewarding authors of articles for the TERA Content Fund</a>
<p>We are pleased to inform you that we are rewarding two authors of articles...</p>
</div>
<p><button type="button" onclick="location.href='/blog/5-rewarding-authors-of-articles-for-the-tera-fontent-fund.html';" class="btn btn-secondary news-btn">READ MORE</button></p>
</div>
<div class="col-md-4">
<div class="about bg-grey last-news-panel">
<img src="/blog/uploads/1/1_1.png" alt="TERA Blockchain News" />
<p>10-March-2019</p>
<a href="/blog/4-tera-blockchain-news.html">TERA Blockchain News</a>
<p>With the large amounts of data that will inevitably occur at 1000 tps, new users should be able to quickly download the blockchain to validate it and start working with it.</p>
</div>
<p><button type="button" onclick="location.href='/blog/4-tera-blockchain-news.html';" class="btn btn-secondary news-btn">READ MORE</button></p>
</div>
<div class="col-md-4">
<div class="about bg-grey last-news-panel">
<img src="/blog/uploads/3/3_1.jpg" alt="TERA Frequently Asked Questions Section" />
<p>07-March-2019</p>
<a href="/blog/3-tera-faq-section.html">TERA Frequently Asked Questions Section</a>
<p>Today, the community receives many questions from various user groups, and in this regard, it was decided to create an Frequently Asked Questions section on the site.</p>
</div>
<p><button type="button" onclick="location.href='/blog/3-tera-faq-section.html';" class="btn btn-secondary news-btn">READ MORE</button></p>
</div>
</div>
</div>
</div>
<!-- Specification -->
<div id="technology" class="section md-padding bg-grey">
@ -169,8 +124,8 @@
<div class="row">
<!-- Section header -->
<div class="section-header">
<h2>Technology</h2>
<div class="section-header text-center">
<h2>Specification</h2>
</div>
<!-- /Section header -->
<div class="no-more-tables">
@ -230,6 +185,25 @@
</div>
<!-- /Specification -->
<!-- News-->
<div id="lastnews" class="section md-padding bg-grey">
<!-- Container -->
<div class="container">
<!-- Row -->
<div class="row">
<!-- Section header -->
<div class="no-more-tables">
{{Edit=./SITE/CONTENT/en-index-lastnews.md}}
</div>
</div>
</div>
</div>
<!-- /News-->
<!-- Updates -->
<div id="updates" class="section md-padding">
@ -239,14 +213,9 @@
<!-- Row -->
<div class="row">
<!-- Section header -->
<div class="section-header">
<h2>Updates</h2>
</div>
<!-- /Section header -->
<div class="no-more-tables">
{{Edit=./SITE/CONTENT/en-index-changelog.md5}}
<p><a href="/changelog.html">Full Changelog</a></p>
{{Edit=./SITE/CONTENT/en-index-changelog.md}}
</div>
</div>
@ -350,20 +319,23 @@
</div>
<div class="roadmap-item__body ">
<div class="roadmap-item__date">
Q1 2019
2019
</div>
<div class="roadmap-item__info">
<ul>
<li>
Android/iOS wallets
</li>
<li>Create and promote TERA Dapps</li>
</ul>
</div>
</div>
</div>
</div>
<!-- /Roadmap Item -->
<!-- /Roadmap Item -->
</div>
</div>
@ -393,13 +365,9 @@
<h3><i class="fas fa-code linksico"></i> FOR DEVELOPERS</h3>
1. <a href="https://sourceforge.net/p/tera/code/ci/master/tree/" target="_blank">TERA Source Code</a>.<br />
2. <a href="https://docs.google.com/document/d/1PXVBbMKdpsAKPkO9UNB5B-LMwIDjylWoHvAAzzrXjvU/edit?usp=sharing/" target="_blank">TERA DApp PAPER (ENG)</a>.<br />
3. <a href="https://docs.google.com/document/d/1SkD4yc_POaGRMJRC6yGkDfdJUuKbcyq3JpG0cBXeYGM/edit?usp=sharing/" target="_blank">TERA DApp PAPER (RUS)</a>.<br />
4. <a href="https://docs.google.com/document/d/10yXAKxaU7YgrQnbdXu_L7WWovUoRtdJwo3tXXaGZGSQ/edit?usp=sharing/" target="_blank">TERA DApp FAQ</a>.<br />
5. <a href="https://sourceforge.net/p/tera/code/ci/master/tree/Doc/Eng/API.md" target="_blank">TERA API</a>.<br />
е. <a href="https://gitlab.com/terafoundation/tera/blob/master/Doc/Eng/API2.md" target="_blank">TERA API-2 (for Exchanges)</a>.<br />
</div>
{{Edit=./SITE/CONTENT/en-index-link-1.md}}
</div>
</div>
<div class="col-md-4">
@ -407,12 +375,8 @@
<h3><i class="fas fa-dollar-sign linksico"></i> FOR INVESTORS</h3>
1. <a href="https://www.qbtc.ink/trade?symbol=TERA_BTC" target="_blank">TERA on QBTC Exchange</a>.<br />
2. <a href="https://www.bitalong.com/trade/index/market/tera_usdt/" target="_blank">TERA on Bitalong Exchange</a>.<br />
3. <a href="https://bitmesh.com/exchange?market=btc_tera#/" target="_blank">TERA on Bitmesh Exchange</a>.<br />
4. <a href="https://chaoex-en-us.udesk.cn/hc/articles/83487" target="_blank">TERA on CHAOEX Exchange</a>.<br />
5. <a href="https://www.citex.co.kr/#/trade/2/37" target="_blank">TERA on CITEX Exchange</a>.<br />
6. <a href="/#roadmap" target="_blank">TERA Roadmap</a>.
{{Edit=./SITE/CONTENT/en-index-link-2.md}}
</div>
</div>
@ -421,9 +385,9 @@
<h3><i class="fas fa-server linksico"></i> FOR MINERS</h3>
1. <a href="https://sourceforge.net/p/tera/code/ci/master/tree/README.md" target="_blank">TERA Mining Documentation</a>.<br />
2. <a href="https://docs.google.com/document/d/18DtASGhrbRwXCAkQR1hQG0lVdrStp4CgA-pd6hicwfo/edit?usp=sharing/" target="_blank">TERA HAASH</a>.
</div>
{{Edit=./SITE/CONTENT/en-index-link-3.md}}
</div>
</div>
<div class="col-md-4">
@ -431,15 +395,9 @@
<h3><i class="fas fa-info-circle linksico"></i> TERA INFORMATION</h3>
1. <a href="https://terafoundation.org/" target="_blank">TERA Website</a>.<br />
2. <a href="https://terafoundation.org/explorer.html" target="_blank">TERA EXPLORER</a>.<br />
3. <a href="https://terafoundation.org/web-wallet.html" target="_blank">TERA WALLET</a>.<br />
4. <a href="https://terafoundation.org/map.html" target="_blank">TERA NETWORK MAP</a>.<br />
5. <a href="https://terafoundation.org/files/TERA_WP_EN.pdf" target="_blank">TERA WHITE PAPER (EN)</a>.<br />
6. <a href="https://terafoundation.org/files/TERA_WP_RU.pdf" target="_blank">TERA WHITE PAPER (RU)</a>.<br />
7. <a href="https://terafoundation.org/files/TERA_WP_DE.pdf" target="_blank">TERA WHITE PAPER (DE)</a>.<br />
8. <a href="https://sourceforge.net/p/tera/code/ci/master/tree/Doc/Chinese/WP_chinese.pdf?format=raw" target="_blank">TERA WHITE PAPER (CN)</a>.<br />
</div>
{{Edit=./SITE/CONTENT/en-index-link-4.md}}
</div>
</div>
<div class="col-md-4">
@ -447,12 +405,8 @@
<h3><i class="fas fa-globe linksico"></i> TERA COMMUNITY</h3>
1. <a href="https://bitcointalk.org/index.php?topic=4573801.0" target="_blank">TERA on BitcoinTalk</a>.<br />
2. <a href="https://twitter.com/terafoundation" target="_blank">TERA on Twitter</a>.<br />
3. <a href="https://www.reddit.com/user/Terafoundation" target="_blank">TERA on Reddit</a>.<br />
4. <a href="https://discord.gg/CvwrbeG" target="_blank">TERA on Discord</a>.<br />
5. <a href="https://web.telegram.org/#/im?p=@terafoundation" target="_blank">TERA Telegram Chanel</a>.<br />
6. <a href="https://jq.qq.com/?_wv=1027&k=58VsQxc" target="_blank">TERA on QQ</a>.
{{Edit=./SITE/CONTENT/en-index-link-5.md}}
</div>
</div>
@ -461,7 +415,8 @@
<h3><i class="fas fa-handshake linksico"></i> OTHER</h3>
1. <a href="http://freetimes.cc/fmessenger/" target="_blank">FMessenger</a>.
{{Edit=./SITE/CONTENT/en-index-link-6.md}}
</div>
</div>
<!-- /About Tera content -->

View File

@ -82,7 +82,7 @@
<ul class="main-nav nav navbar-nav navbar-right white_menu">
<li><a href="index.html">HOME</a></li>
<li><a href="/changelog.html">CHANGELOG</a></li>
<li><a href="/token.html">TOKEN</a></li>
<li><a href="/token.html">COIN</a></li>
<li><a href="/tera-content-fund.html">CONTENT FUND</a></li>
<li><a href="/blog/">BLOG</a></li>
<li><a href="/explorer.html">EXPLORER</a></li>

24
Source/SITE/metrika.html Normal file
View File

@ -0,0 +1,24 @@
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'UA-135904501-1');
</script>

View File

@ -1,7 +1,7 @@
<ul class="main-nav nav navbar-nav navbar-right white_menu">
<li><a href="/#about">ABOUT</a></li>
<!--li><a href="/changelog.html">CHANGELOG</a></li-->
<li><a href="/tera-token.html">TERA TOKEN</a></li>
<li><a href="/tera-token.html">TERA COIN</a></li>
<li><a href="/blog/">BLOG</a></li>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="../CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="../CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -51,30 +51,9 @@
}
</style>
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -1,7 +1,7 @@
<ul class="main-nav nav navbar-nav navbar-right white_menu">
<li><a href="#about">О TERA</a></li>
<!--li><a href="/ru/changelog.html">CHANGELOG</a></li-->
<li><a href="/ru/tera-token.html">ТОКЕН TERA</a></li>
<li><a href="/ru/tera-token.html">МОНЕТА TERA</a></li>
<li><a href="/blog/" target="_blank">БЛОГ</a></li>

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<title>TERA Foundation: TOKEN</title>
<title>TERA Foundation: COIN</title>
<meta data-n-head="true" data-hid="description" name="description" content="Tera - Fast block generation, High transaction throughput, User-friendly">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="../CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<title>TERA Foundation: TOKEN</title>
<title>TERA Foundation: COIN</title>
<meta data-n-head="true" data-hid="description" name="description" content="Tera - Fast block generation, High transaction throughput, User-friendly">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="../CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<title>TERA Foundation: TOKEN</title>
<title>TERA Foundation: COIN</title>
<meta data-n-head="true" data-hid="description" name="description" content="Tera - Fast block generation, High transaction throughput, User-friendly">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>

View File

@ -2,7 +2,7 @@
<html lang="en">
<head>
<title>TERA Foundation: TOKEN</title>
<title>TERA Foundation: COIN</title>
<meta data-n-head="true" data-hid="description" name="description" content="Tera - Fast block generation, High transaction throughput, User-friendly">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@ -21,30 +21,9 @@
<!-- Custom stlylesheet -->
<link type="text/css" rel="stylesheet" href="CSS/style.min.css" />
<!-- Yandex.Metrika counter -->
<script type="text/javascript" >
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(52744594, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/52744594" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-135904501-1"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
{{File=./SITE/metrika.html}}
gtag('config', 'UA-135904501-1');
</script>
</head>
<body>
@ -115,7 +94,7 @@
<!-- About Tera content -->
<div class="col-md-12 about-panel">
<div class="section-header text-center">
<h1>TERA TOKEN</h1>
<h1>TERA COIN</h1>
</div>
<p>
TERA is a coin that provides solutions to existing cryptocurrency issues, namely de-neutralization, transaction

View File

@ -1293,7 +1293,7 @@ module.exports = class CConsensus extends require("./block-loader")
if(GrayConnect())
{
if(!this.LoadHistoryMode)
this.StartLoadHistory(undefined, 1)
this.StartSyncBlockchain(undefined, 1)
return ;
}
if(this.LoadHistoryMode)
@ -1440,11 +1440,12 @@ module.exports = class CConsensus extends require("./block-loader")
if(PrevBlock.bSave && this.BlockNumDB + 1 >= Block.BlockNum)
{
this.AddToStatBlockConfirmation(Block)
var Power = GetPowPower(Block.PowHash);
if(this.WriteBlockDB(Block))
{
if(Block.arrContent && Block.arrContent.length)
ADD_TO_STAT("MAX:TRANSACTION_COUNT", Block.arrContent.length)
AddInfoBlock(Block, "SAVE TO DB: " + GetPowPower(Block.PowHash))
AddInfoBlock(Block, "SAVE:" + Power + " TH:" + this.GetStrFromHashShort(Block.TreeHash).substr(0, 4))
}
else
{
@ -1452,6 +1453,34 @@ module.exports = class CConsensus extends require("./block-loader")
AddInfoBlock(Block, "ERROR WRITE DB")
}
this.AddToMaxSum(Block, {SumHash:Block.SumHash, SumList:this.GetBlockList(Block.BlockNum), })
if(typeof global.RESYNC_CONDITION === "object")
{
if(!this.OwnBlockCount)
this.OwnBlockCount = 0
var Miner = ReadUintFromArr(Block.AddrHash, 0);
var MultK = RESYNC_CONDITION.K_POW;
var MaxBlocks = RESYNC_CONDITION.OWN_BLOCKS;
if(Miner === GENERATE_BLOCK_ACCOUNT)
{
this.OwnBlockCount++
if(this.OwnBlockCount >= MaxBlocks)
{
var PrevSumPow = this.GetAvgPowBlock(Block.BlockNum - 2 * MaxBlocks, MaxBlocks);
var CurrentPow = this.GetAvgPowBlock(Block.BlockNum - MaxBlocks, MaxBlocks);
if(CurrentPow === 0 || PrevSumPow / CurrentPow >= MultK)
{
ToLog("START RESYNC CONDITION")
this.OwnBlockCount = 0
this.StartSyncBlockchain()
return ;
}
}
}
else
{
this.OwnBlockCount = 0
}
}
}
else
{
@ -1476,6 +1505,25 @@ module.exports = class CConsensus extends require("./block-loader")
this.RelayMode = !bWasSave
this.FREE_MEM_BLOCKS(CURRENTBLOCKNUM - BLOCK_COUNT_IN_MEMORY)
}
GetAvgPowBlock(StartNum, CountNum)
{
var Count = 0;
var SumPow = 0;
for(var Num = StartNum; Num < StartNum + CountNum; Num++)
{
var Block = this.GetBlock(Num);
if(Block && Block.bSave)
{
var Power = GetPowPower(Block.PowHash);
SumPow += Power
Count++
}
}
if(!Count)
return 0;
else
return SumPow / Count;
}
CreatePOWNew(Block)
{
CreateHashMinimal(Block, GENERATE_BLOCK_ACCOUNT)
@ -1556,12 +1604,6 @@ module.exports = class CConsensus extends require("./block-loader")
}
};
global.TreeBlockBuf = new STreeBuffer(50 * 1000, CompareItemHashSimple, "string");
global.GetCurrentBlockNumByTime = function GetCurrentBlockNumByTime()
{
var CurTimeNum = GetCurrentTime() - FIRST_TIME_BLOCK;
var StartBlockNum = Math.trunc((CurTimeNum + CONSENSUS_PERIOD_TIME) / CONSENSUS_PERIOD_TIME);
return StartBlockNum;
};
var PrevTimeIdle = 0;
OnTimeIdle();

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://web.telegram.org/#/im?p=@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 = 1e3, global.MAX_SMARTS_TRANSFER = 10, global.TEST_NETWORK && (global.MAX_ACCOUNTS_TRANSFER = 100,
global.MAX_SMARTS_TRANSFER = 10), global.FORMAT_REST_TRANSFER = "{ Result:uint, BlockNum:uint, Arr:[arr200], }",
global.FORMAT_SMART_TRANSFER = "{ Result:uint, Arr:[tr], }";

View File

@ -11,27 +11,9 @@
"use strict";
const fs = require("fs");
const crypto = require('crypto');
require('./block-loader-const');
const STAT_BLOCK_LOAD_PERIOD = CONSENSUS_PERIOD_TIME / 5;
global.PERIOD_GET_BLOCK = 300;
if(global.LOCAL_RUN || global.TEST_NETWORK)
{
global.COUNT_BLOCKS_FOR_LOAD = global.DELTA_BLOCK_ACCOUNT_HASH / 2;
}
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;
const Formats = {BLOCK_TRANSFER:"{\
BlockNum:uint,\
TreeHash:hash,\
arrContent:[tr],\
}",
WRK_BLOCK_TRANSFER:{}, };
module.exports = class CBlock extends require("./db/block-db")
module.exports = class CBlock extends require("./rest-loader.js")
{
constructor(SetKeyPair, RunIP, RunPort, UseRNDHeader, bVirtual)
{
@ -145,7 +127,7 @@ module.exports = class CBlock extends require("./db/block-db")
var PrevHash = CalcHashFromArray(arr, true);
return PrevHash;
}
StartLoadHistory(Node, bSilent)
StartSyncBlockchain(Node, bSilent, bCheckPoint)
{
this.FREE_ALL_MEM_CHAINS()
if(global.NO_HISTORY_MODE)
@ -163,11 +145,15 @@ module.exports = class CBlock extends require("./db/block-db")
this.RelayMode = true
this.LoadHistoryMode = true
this.LoadHistoryMessage = !bSilent
this.LoadHistoryContext = {Node:Node, BlockNum:this.BlockNumDB, MapSend:{}, Foward:1, Pause:0, DeltaBlockNum:10}
this.LoadHistoryContext = {PrevBlockNum: - 1, Node:Node, BlockNum:this.BlockNumDB, MapSend:{}, Foward:1, Pause:0, DeltaBlockNum:10,
StartTimeHistory:Date.now(), MaxTimeOut:30 * 1000}
if(!bSilent && !bCheckPoint && REST_START_COUNT)
{
this.CheckSyncRest()
}
if(!this.ActualNodes.size)
{
ToLog("There is no connections to other nodes")
return ;
}
else
{
@ -177,6 +163,60 @@ module.exports = class CBlock extends require("./db/block-db")
}
}
}
LoopSyncBlockchain()
{
if(!this.ActualNodes.size)
return ;
var Context;
if(this.LoadRestContext && this.LoadRestContext.Mode < 200)
Context = this.LoadRestContext
else
Context = this.LoadHistoryContext
if(Context.PrevBlockNum === Context.BlockNum)
{
var DeltaTime = Date.now() - Context.StartTimeHistory;
if(DeltaTime > Context.MaxTimeOut)
{
ToLog("DETECT TIMEOUT LOAD")
this.StartSyncBlockchain()
return ;
}
}
else
{
Context.PrevBlockNum = Context.BlockNum
Context.StartTimeHistory = Date.now()
}
if(Context.LoopSyncRest)
{
this.LoopSyncRest()
return ;
}
if(Context.Pause)
{
if(this.LoadedChainList.length)
{
return ;
}
Context.Pause = 0
Context.BlockNum = this.BlockNumDB
}
var BlockDB = this.ReadBlockHeaderDB(Context.BlockNum);
if(!BlockDB || this.BlockNumDB >= GetCurrentBlockNumByTime() - BLOCK_PROCESSING_LENGTH - 2)
{
this.LoadHistoryMode = false
if(this.LoadHistoryMessage)
ToLog("Finish synchronization")
if(!BlockDB)
return ;
}
var Ret = this.GetNextNode(Context, Context.BlockNum, 1);
if(Ret.Result)
{
var Node = Ret.Node;
this.SendF(Node, {"Method":"GETBLOCKHEADER", "Context":Context, "Data":{Foward:1, BlockNum:Context.BlockNum, Hash:BlockDB.SumHash}})
}
}
StartLoadBlockHeader(LoadHash, Num, StrInfo, bIsSum)
{
if(this.LoadHistoryMode)
@ -208,51 +248,6 @@ module.exports = class CBlock extends require("./db/block-db")
}
return true;
}
LoopHistoryLoad()
{
if(!this.ActualNodes.size)
return ;
var Context = this.LoadHistoryContext;
if(Context.PrevBlockNum === Context.BlockNum)
{
var DeltaTime = Date.now() - Context.StartTimeHistory;
if(DeltaTime > 30 * 1000)
{
ToLog("DETECT TIMEOUT LOADHISTORY")
this.StartLoadHistory()
return ;
}
}
else
{
Context.PrevBlockNum = Context.BlockNum
Context.StartTimeHistory = Date.now()
}
if(Context.Pause)
{
if(this.LoadedChainList.length)
{
return ;
}
Context.Pause = 0
Context.BlockNum = this.BlockNumDB
}
var BlockDB = this.ReadBlockHeaderDB(Context.BlockNum);
if(!BlockDB || this.BlockNumDB >= GetCurrentBlockNumByTime() - BLOCK_PROCESSING_LENGTH - 2)
{
this.LoadHistoryMode = false
if(this.LoadHistoryMessage)
ToLog("Finish synchronization")
if(!BlockDB)
return ;
}
var Ret = this.GetNextNode(Context, Context.BlockNum, 1);
if(Ret.Result)
{
var Node = Ret.Node;
this.SendF(Node, {"Method":"GETBLOCKHEADER", "Context":Context, "Data":{Foward:1, BlockNum:Context.BlockNum, Hash:BlockDB.SumHash}})
}
}
SetChainNum(chain)
{
if(!chain.id)
@ -270,12 +265,12 @@ module.exports = class CBlock extends require("./db/block-db")
this.TruncateBlockDB(this.UseTruncateBlockDB)
if(this.LoadHistoryMode)
{
this.LoopHistoryLoad()
this.LoopSyncBlockchain()
return ;
}
if(this.BlockNumDB < this.CurrentBlockNum - BLOCK_PROCESSING_LENGTH2)
{
this.StartLoadHistory()
this.StartSyncBlockchain()
return ;
}
var CountStopSend = 0;
@ -502,6 +497,12 @@ module.exports = class CBlock extends require("./db/block-db")
bFindDB = 1
arr2.push(Block)
}
else
if(BlockDB && IsZeroArr(BlockDB.SumHash))
{
bFindDB = 1
arr2.push(Block)
}
}
else
if(bFindDB)
@ -832,19 +833,22 @@ module.exports = class CBlock extends require("./db/block-db")
var Block, FirstBlock;
for(var i = 0; i < arr.length; i++)
{
if(arr[i].BlockNum > this.BlockNumDB + 1)
break;
Block = arr[i]
if(Block.BlockNum > this.BlockNumDB + 1)
break;
if(!FirstBlock)
FirstBlock = Block
Block.BlockDown = undefined
var PrevHash = this.GetPrevHashDB(Block);
if(CompareArr(PrevHash, Block.PrevHash) !== 0)
if(Block.BlockNum > this.BlockNumDBMin + BLOCK_PROCESSING_LENGTH2)
{
if(global.WATCHDOG_DEV)
ToError("******** ERROR LOADED DATA Count:" + arr.length + " AT BLOCK NUM:" + Block.BlockNum + " (" + arr[0].BlockNum + "-" + arr[arr.length - 1].BlockNum + ")")
this.FREE_ALL_MEM_CHAINS()
return ;
var PrevHash = this.GetPrevHashDB(Block);
if(CompareArr(PrevHash, Block.PrevHash) !== 0)
{
if(global.WATCHDOG_DEV)
ToError("******** ERROR LOADED DATA Count:" + arr.length + " AT BLOCK NUM:" + Block.BlockNum + " (" + arr[0].BlockNum + "-" + arr[arr.length - 1].BlockNum + ")")
this.FREE_ALL_MEM_CHAINS()
return ;
}
}
var Res = 0;
if(Block.TreeEq)
@ -883,7 +887,9 @@ module.exports = class CBlock extends require("./db/block-db")
}
var BlockMem = this.BlockChain[Block.BlockNum];
if(BlockMem)
AddInfoBlock(BlockMem, "Load:" + GetPowPower(Block.PowHash))
{
AddInfoBlock(BlockMem, "LOAD:" + GetPowPower(Block.PowHash) + " TH:" + this.GetStrFromHashShort(Block.TreeHash).substr(0, 4))
}
}
if(Block && FirstBlock)
{
@ -1076,7 +1082,7 @@ module.exports = class CBlock extends require("./db/block-db")
var Block = Info.Context.Block;
if(Block && !Block.TreeEq)
{
var Data = BufLib.GetObjectFromBuffer(Info.Data, Formats.BLOCK_TRANSFER, Formats.WRK_BLOCK_TRANSFER);
var Data = BufLib.GetObjectFromBuffer(Info.Data, FORMAT_BLOCK_TRANSFER, WRK_BLOCK_TRANSFER);
Info.Data = undefined
if(Data.BlockNum !== Block.BlockNum || CompareArr(Data.TreeHash, Block.TreeHash) !== 0)
{
@ -1429,106 +1435,41 @@ function GetFindDB()
this.SetChainNum(chain)
this.PrepareTransactionsForLoad(chain, arr, 1)
}
static
GETREST_F()
};
global.LoadBlockFromNetwork = function (Params,F)
{
var BlockNum = Params.BlockNum;
if(BlockNum >= SERVER.BlockNumDBMin)
{
return "{\
BlockNum:uint,\
StartAccount:uint,\
LengthAccount:uint,\
}";
ToLog("Cant LoadBlockFromNetwork:" + BlockNum, 2);
F(1);
return ;
}
static
RETREST_F()
ToLog("DownloadBlockFromNetwork:" + BlockNum, 2);
var TaskLoadBlockFromNetwork = {MapSend:{}};
var Ret = SERVER.GetNextNode(TaskLoadBlockFromNetwork, BlockNum, 1);
if(Ret.Result)
{
return "{\
Result:uint,\
BlockNum:uint,\
Arr:[arr200],\
}";
}
GetRestAcc(Node, Delta)
{
var BlockNumRest = GetCurrentRestNum(Delta);
this.SendF(Node, {"Method":"GETREST", "Context":{BlockNum:BlockNumRest}, "Data":{BlockNum:BlockNumRest, StartAccount:0}})
return BlockNumRest;
}
GETREST(Info, CurTime)
{
var Data = this.DataFromF(Info);
if(!Data.BlockNum)
return ;
var BlockNumRest = Data.BlockNum;
var arr = GetCurrentRestArr();
var BufLength;
var nResult = 0;
for(var i = 0; i < arr.length; i++)
{
if(arr[i] === BlockNumRest)
{
nResult = 1
break;
}
}
var ArrRest = [];
if(nResult)
{
var WorkStruct = {};
var WorkFormat = DApps.Accounts.FORMAT_ACCOUNT_ROW;
var WorkFormatLength = DApps.Accounts.SIZE_ACCOUNT_ROW;
var Max = DApps.Accounts.DBState.GetMaxNum();
var FindItem;
for(var Num = 0; Num <= Max; Num++)
{
FindItem = undefined
var RestData = DApps.Accounts.ReadRest(Num);
var Data = DApps.Accounts.DBState.Read(Num);
if(!Data)
break;
var CountZero = 0;
for(var i = RestData.Arr.length - 1; i >= 0; i--)
let Node = Ret.Node;
SERVER.SendF(Node, {"Method":"GETBLOCK", "Data":{BlockNum:BlockNum, TreeHash:[]}, "Context":{F:function (Info)
{
var Item = RestData.Arr[i];
if(!Item.BlockNum)
var Block = BufLib.GetObjectFromBuffer(Info.Data, FORMAT_BLOCK_TRANSFER, WRK_BLOCK_TRANSFER);
Info.Data = undefined;
if(Block.BlockNum !== BlockNum)
{
CountZero++
continue;
ToLog("Error get BlockNum:" + BlockNum + " from " + NodeName(Info.Node), 2);
F(1);
return ;
}
if(Item.BlockNum <= BlockNumRest)
{
if(!FindItem || Item.BlockNum > FindItem.BlockNum)
{
FindItem = Item
}
}
}
if(FindItem)
{
Data.Value = FindItem.Value
}
else
{
if(CountZero !== RestData.Arr.length)
continue;
}
var Buf = BufLib.GetBufferFromObject(Data, WorkFormat, WorkFormatLength, WorkStruct);
ArrRest.push(Buf)
}
BufLength = 1000 + ArrRest.length * WorkFormatLength
}
else
{
BufLength = 1000
}
this.SendF(Info.Node, {"Method":"RETREST", "Context":Info.Context, "Data":{Result:nResult, BlockNum:BlockNumRest, Arr:ArrRest}},
BufLength)
ToLog("Got BlockFromNetwork:" + BlockNum, 2);
SERVER.WriteBlockDB(Block);
F(0, Block);
}}, });
}
RETREST(Info, CurTime)
else
{
var Data = this.DataFromF(Info);
if(!Data.BlockNum || Data.BlockNum !== Info.Context.BlockNum)
return ;
ToLog("Get Rest on: " + Data.BlockNum + " Arr=" + Data.Arr.length)
ToLog("Not find node for download block", 2);
F(1);
}
};
global.HistoryBlockBuf = new STreeBuffer(HISTORY_BLOCK_COUNT * 1000, CompareItemHashSimple, "string");

View File

@ -372,14 +372,16 @@ module.exports = class CConnect extends require("./transfer-msg")
var SignArr = arr2(Data.CheckPoint.Hash, GetArrFromValue(Data.CheckPoint.BlockNum));
if(CheckDevelopSign(SignArr, Data.CheckPoint.Sign))
{
this.ResetNextPingAllNode()
global.CHECK_POINT = Data.CheckPoint
this.ResetNextPingAllNode()
if(Data.CheckPoint.BlockNum < this.BlockNumDBMin)
return ;
var Block = this.ReadBlockHeaderDB(CHECK_POINT.BlockNum);
if(Block && CompareArr(Block.Hash, CHECK_POINT.Hash) !== 0)
{
this.BlockNumDB = CHECK_POINT.BlockNum - 1
this.TruncateBlockDB(this.BlockNumDB)
this.StartLoadHistory(Node)
this.StartSyncBlockchain(Node, 0, 1)
}
}
else
@ -423,7 +425,7 @@ module.exports = class CConnect extends require("./transfer-msg")
{
Node.VersionOK = false
}
if(Node.VersionOK && !Data.LoadHistoryMode)
if(Node.VersionOK)
{
Node.CanHot = true
if(CHECK_POINT.BlockNum && Data.CheckPoint.BlockNum)

View File

@ -8,8 +8,8 @@
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
*/
global.UPDATE_CODE_VERSION_NUM = 925;
global.MIN_CODE_VERSION_NUM = 920;
global.UPDATE_CODE_VERSION_NUM = 992;
global.MIN_CODE_VERSION_NUM = 922;
global.MINING_VERSION_NUM = 3;
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",
@ -18,10 +18,8 @@ global.CONST_NAME_ARR = ["AUTO_CORRECT_TIME", "DELTA_CURRENT_TIME", "COMMON_KEY"
"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", "COREY_WATCH_DOG", "MAX_CONNECTIONS_COUNT",
"TRUST_PROCESS_COUNT", "TRUST_BLOCKS_COUNT", ];
global.REST_BLOCK_SCALE = 1000;
global.TRUST_BLOCKS_COUNT = 3600;
"HTTPS_HOSTING_DOMAIN", "HTTP_MAX_COUNT_ROWS", "HTTP_ADMIN_PASSORD", "WATCHDOG_BADACCOUNT", "RESYNC_CONDITION", "MAX_CONNECTIONS_COUNT",
"TRUST_PROCESS_COUNT", "REST_START_COUNT", ];
global.USE_HARD_API_V2 = 0;
global.USE_TICKET = 0;
global.USE_CHECK_SENDING = 1;
@ -30,8 +28,9 @@ global.TR_TICKET_HASH_LENGTH = 10;
global.BLOCKNUM_TICKET_ALGO = 16070000;
global.WATCHDOG_BADACCOUNT = 1;
global.WATCHDOG_DEV = 0;
global.COREY_WATCH_DOG = 0;
global.WATCHDOG_ORPHAN = 0;
global.RESYNC_CONDITION = {"OWN_BLOCKS":10, "K_POW":10};
global.REST_BLOCK_SCALE = 1000;
global.REST_START_COUNT = 0;
global.DEBUG_WALLET = 0;
global.CHECK_GLOBAL_TIME = 1;
global.AUTO_CORRECT_TIME = 1;
@ -74,6 +73,7 @@ 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;
@ -107,6 +107,7 @@ 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_BLOCK_REWARD2 = 30000000;
@ -136,6 +137,7 @@ if(global.LOCAL_RUN)
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;
@ -147,6 +149,7 @@ if(global.LOCAL_RUN)
global.NEW_BLOCK_REWARD1 = 1;
NETWORK = "LOCAL";
global.ALL_VIEW_ROWS = 1;
global.COUNT_NODE_PROOF = 1;
}
else
if(global.TEST_NETWORK)
@ -158,12 +161,11 @@ else
global.START_NETWORK_DATE = 1550843168000 + 1000 * 1000;
global.START_MINING = 1000;
global.REF_PERIOD_MINING = 1000;
global.MIN_POWER_POW_TR = 8;
global.MIN_POWER_POW_ACC_CREATE = 8;
global.TRANSACTION_PROOF_COUNT = 200 * 1000;
global.MAX_SIZE_LOG = 20 * 1024 * 1024;
global.DELTA_BLOCK_ACCOUNT_HASH = 1000;
global.START_BLOCK_ACCOUNT_HASH = 1000;
global.START_BLOCK_ACCOUNT_HASH3 = 2356000;
global.BLOCKNUM_TICKET_ALGO = 1;
global.WALLET_NAME = "TEST";
NETWORK = "TERA-TEST2";
@ -172,6 +174,8 @@ else
global.ALL_VIEW_ROWS = 1;
global.NEW_ACCOUNT_INCREMENT = 1903000;
global.NEW_BLOCK_REWARD1 = 1905000;
global.COUNT_NODE_PROOF = 8;
global.REST_START_COUNT = 10000;
}
if(global.LOCAL_RUN)
{

View File

@ -24,6 +24,7 @@ module.exports = class CDB extends require("../code")
BlockDB.OpenDBFile(FILE_NAME_HEADER, bWriteMode)
BlockDB.OpenDBFile(FILE_NAME_BODY, bWriteMode)
this.BlockNumDB = 0
this.BlockNumDBMin = 0
this.ClearBufMap()
}
LoadMemBlocksOnStart()
@ -46,11 +47,17 @@ module.exports = class CDB extends require("../code")
}
FindStartBlockNum()
{
var StateTX = DApps.Accounts.DBStateTX.Read(0);
if(StateTX)
{
this.BlockNumDBMin = StateTX.BlockNumMin
}
ToLog("BlockNumDBMin=" + this.BlockNumDBMin, 2)
var BlockNum = this.GetMaxNumBlockDB();
if(global.NO_CHECK_BLOCKNUM_ONSTART)
{
this.BlockNumDB = this.CheckBlocksOnStartFoward(BlockNum - 2, 0)
ToLog("START_BLOCK_NUM:" + this.BlockNumDB)
ToLog("START_BLOCK_NUM:" + this.BlockNumDB, 2)
return ;
}
BlockNum = this.CheckBlocksOnStartReverse(BlockNum)
@ -60,7 +67,7 @@ module.exports = class CDB extends require("../code")
{
this.TruncateBlockDB(this.BlockNumDB)
}
ToLog("START_BLOCK_NUM:" + this.BlockNumDB)
ToLog("START_BLOCK_NUM:" + this.BlockNumDB, 2)
this.CheckOnStartComplete = 1
}
CheckBlocksOnStartReverse(StartNum)
@ -68,7 +75,7 @@ module.exports = class CDB extends require("../code")
var delta = 1;
var Count = 0;
var PrevBlock;
for(var num = StartNum; num >= BLOCK_PROCESSING_LENGTH; num -= delta)
for(var num = StartNum; num >= this.BlockNumDBMin + BLOCK_PROCESSING_LENGTH2; num -= delta)
{
var Block = this.ReadBlockHeaderDB(num);
if(!Block || IsZeroArr(Block.SumHash))
@ -102,8 +109,8 @@ module.exports = class CDB extends require("../code")
CheckBlocksOnStartFoward(StartNum, bCheckBody)
{
var PrevBlock;
if(StartNum < BLOCK_PROCESSING_LENGTH2)
StartNum = BLOCK_PROCESSING_LENGTH2
if(StartNum < this.BlockNumDBMin + BLOCK_PROCESSING_LENGTH2)
StartNum = this.BlockNumDBMin + BLOCK_PROCESSING_LENGTH2
var MaxNum = DApps.Accounts.GetHashedMaxBlockNum();
var BlockNumTime = GetCurrentBlockNumByTime();
if(BlockNumTime < MaxNum)
@ -193,7 +200,8 @@ module.exports = class CDB extends require("../code")
throw "ERROR WRITE";
}
this.OnWriteBlock(Block)
this.BlockNumDB = Block.BlockNum
if(Block.BlockNum > this.BlockNumDBMin)
this.BlockNumDB = Block.BlockNum
Block.bSave = true
}
return Ret;
@ -281,7 +289,7 @@ module.exports = class CDB extends require("../code")
}
WriteBlockHeaderDB(Block)
{
if(Block.BlockNum > 0)
if(Block.BlockNum > this.BlockNumDBMin + BLOCK_PROCESSING_LENGTH2)
{
if(USE_CHECK_SAVE_DB)
if(!this.CheckSeqHashDB(Block, "WriteBlockHeaderDB"))
@ -298,6 +306,10 @@ module.exports = class CDB extends require("../code")
Block.SumHash = shaarr2(PrevBlock.SumHash, Block.Hash)
Block.SumPow = PrevBlock.SumPow + GetPowPower(Block.PowHash)
}
else
{
var Stop = 1;
}
var BufWrite = BufLib.GetNewBuffer(BLOCK_HEADER_SIZE);
this.BlockHeaderToBuf(BufWrite, Block)
var Res = this.WriteBufHeaderDB(BufWrite, Block.BlockNum);
@ -441,7 +453,7 @@ module.exports = class CDB extends require("../code")
var Block = this.ReadBlockDB(LastBlockNum);
if(!Block)
{
ToLog("************ ERROR TruncateBlockDB - not found block=" + LastBlockNum)
ToLog("************ ERROR TruncateBlockDB - not found block=" + LastBlockNum, 2)
return ;
}
this.WriteBlockDB(Block)
@ -489,7 +501,8 @@ module.exports = class CDB extends require("../code")
}
ClearDataBase()
{
this.RewriteAllTransactions()
if(global.TX_PROCESS && global.TX_PROCESS.RunRPC)
global.TX_PROCESS.RunRPC("ClearDataBase", {})
var FItem1 = BlockDB.OpenDBFile(FILE_NAME_HEADER, 1);
FItem1.size = 0
fs.ftruncateSync(FItem1.fd, FItem1.size)
@ -497,9 +510,11 @@ module.exports = class CDB extends require("../code")
FItem2.size = 0
fs.ftruncateSync(FItem2.fd, FItem2.size)
this.BlockNumDB = 0
this.BlockNumDBMin = 0
this.ClearBufMap()
this.ClearStat()
this.CreateGenesisBlocks()
this.StartSyncBlockchain()
}
ClearBufMap()
{
@ -509,8 +524,11 @@ module.exports = class CDB extends require("../code")
{
if(TX_PROCESS.Worker)
{
TX_PROCESS.Worker.send({cmd:"RewriteAllTransactions"})
return 1;
if(global.TX_PROCESS && global.TX_PROCESS.RunRPC)
{
global.TX_PROCESS.RunRPC("RewriteAllTransactions", {})
return 1;
}
}
return 0;
}
@ -877,57 +895,45 @@ module.exports = class CDB extends require("../code")
if(StartNum === undefined)
return BufLib.GetNewBuffer(10);
var GetLength = EndBlockNum - StartNum + 1;
var PrevBlock;
if(StartNum > 0)
PrevBlock = this.ReadBlockHeaderDB(StartNum - 1)
var arr = [];
var arr0 = this.PrevBlockChainArr;
if(arr0 && arr0.length === GetLength)
if(arr0 && arr0.length)
{
var StartNumArr = - 1;
var EndNumArr = - 1;
for(var i = 0; i < arr0.length; i++)
var Block = arr0[arr0.length - 1];
if(Block.BlockNum >= StartNum && Block.BlockNum <= EndBlockNum)
{
var BlockArr = arr0[i];
if(BlockArr.BlockNum === StartNum)
var BlockDB = this.ReadBlockHeaderDB(Block.BlockNum);
if(!BlockDB || CompareArr(Block.SumHash, BlockDB.SumHash) !== 0)
{
StartNumArr = i
arr0 = undefined
}
if(BlockArr.BlockNum <= EndBlockNum)
else
{
EndNumArr = i
}
}
if(StartNumArr >= 0 && EndNumArr > StartNumArr)
{
var BlockArr = arr0[EndNumArr];
var Block = this.ReadBlockHeaderDB(BlockArr.BlockNum);
if(Block)
if(CompareArr(BlockArr.SumHash, Block.SumHash) == 0)
{
arr0.splice(EndNumArr + 1, arr.length)
if(StartNumArr > 0)
arr0.splice(StartNumArr - 1, StartNumArr)
arr = arr0
PrevBlock = Block
StartNum = Block.BlockNum + 1
}
}
}
var i0 = 0;
for(var num = StartNum; num <= EndBlockNum; num++)
{
var Block = this.ReadBlockHeaderDB(num);
var Block = undefined;
if(arr0)
{
for(var i = i0; i < arr0.length; i++)
{
i0 = i
var Block0 = arr0[i];
if(Block0.BlockNum === num)
{
Block = Block0
break;
}
}
}
if(!Block)
Block = this.ReadBlockHeaderDB(num)
if(!Block || !Block.Prepared || !Block.Hash)
break;
if(PrevBlock)
{
if(!PrevBlock.SumHash)
break;
var SumHash = shaarr2(PrevBlock.SumHash, Block.Hash);
Block.SumHash = SumHash
}
arr.push(Block)
PrevBlock = Block
}
this.PrevBlockChainArr = arr
return this.ArrHeaderToBuf(WriteNum, arr);

View File

@ -209,62 +209,126 @@ function SendBlockFile(response,BlockNum,TrNum)
{
BlockNum = parseInt(BlockNum);
TrNum = parseInt(TrNum);
if(BlockNum && TrNum <= MAX_TRANSACTION_COUNT)
if(BlockNum && BlockNum <= SERVER.GetMaxNumBlockDB() && TrNum <= MAX_TRANSACTION_COUNT)
{
var Block = SERVER.ReadBlockDB(BlockNum);
if(Block && Block.arrContent)
{
var Body = Block.arrContent[TrNum];
if(Body && Body[0] === global.TYPE_TRANSACTION_FILE)
{
var TR = DApps.File.GetObjectTransaction(Body);
if(TR.ContentType.toLowerCase().indexOf("html") >= 0)
response.writeHead(200, {'Content-Type':"text/plain"});
else
response.writeHead(200, {'Content-Type':TR.ContentType});
response.end(TR.Data);
}
SendToResponceFile(response, Block, TrNum);
return ;
}
else
if(!Block || !Block.TrDataPos)
{
LoadBlockFromNetwork({BlockNum:BlockNum}, function (Err,Block)
{
if(Err)
{
SendToResponce404(response);
}
else
{
SendToResponceFile(response, Block, TrNum);
}
});
return ;
}
}
SendToResponce404(response);
};
function SendToResponceFile(response,Block,TrNum)
{
var Body = Block.arrContent[TrNum];
if(Body && Body.data)
Body = Body.data;
if(Body && Body[0] === global.TYPE_TRANSACTION_FILE)
{
var TR = DApps.File.GetObjectTransaction(Body);
if(TR.ContentType.toLowerCase().indexOf("html") >= 0)
response.writeHead(200, {'Content-Type':"text/plain"});
else
response.writeHead(200, {'Content-Type':TR.ContentType});
response.end(TR.Data);
}
else
{
SendToResponce404(response);
}
};
function SendToResponce404(response)
{
response.writeHead(404, {'Content-Type':'text/html'});
response.end();
};
HTTPCaller.DappBlockFile = function (Params)
HTTPCaller.DappBlockFile = function (Params,response)
{
Params.BlockNum = ParseNum(Params.BlockNum);
Params.TrNum = ParseNum(Params.TrNum);
if(!Params.TrNum)
Params.TrNum = 0;
if(Params.BlockNum && Params.TrNum <= MAX_TRANSACTION_COUNT)
if(Params.BlockNum && Params.BlockNum <= SERVER.GetMaxNumBlockDB() && Params.TrNum <= MAX_TRANSACTION_COUNT)
{
var Block = SERVER.ReadBlockDB(ParseNum(Params.BlockNum));
var Block = SERVER.ReadBlockDB(Params.BlockNum);
if(Block && Block.arrContent)
{
var Body = Block.arrContent[ParseNum(Params.TrNum)];
if(Body)
{
var Type = Body[0];
if(Type === global.TYPE_TRANSACTION_FILE)
{
var TR = DApps.File.GetObjectTransaction(Body);
return {result:1, Type:Type, ContentType:TR.ContentType, Name:TR.Name, Body:TR.Data.toString('utf8')};
}
else
{
var App = DAppByType[Type];
if(App)
{
Body = JSON.parse(App.GetScriptTransaction(Body));
}
return {result:1, Type:Type, Body:Body};
}
}
SendToResponceDappFile(response, Block, Params.TrNum);
return null;
}
else
if(!Block || !Block.TrDataPos)
{
LoadBlockFromNetwork(Params, function (Err,Block)
{
if(Err)
{
SendToResponceResult0(response);
}
else
{
SendToResponceDappFile(response, Block, Params.TrNum);
}
});
return null;
}
}
return {result:0};
};
function SendToResponceDappFile(response,Block,TrNum)
{
var Result = {result:0};
var Body = Block.arrContent[TrNum];
if(Body)
{
var Type = Body[0];
if(Type === global.TYPE_TRANSACTION_FILE)
{
var TR = DApps.File.GetObjectTransaction(Body);
Result = {result:1, Type:Type, ContentType:TR.ContentType, Name:TR.Name, Body:TR.Data.toString('utf8')};
}
else
{
var App = DAppByType[Type];
if(App)
{
Body = JSON.parse(App.GetScriptTransaction(Body));
}
Result = {result:1, Type:Type, Body:Body};
}
}
var Str = JSON.stringify(Result);
response.end(Str);
};
function SendToResponceResult0(response)
{
if(response)
response.end("{\"result\":0}");
};
var glBlock0;
HTTPCaller.DappStaticCall = function (Params)
HTTPCaller.DappStaticCall = function (Params,response)
{
DApps.Accounts.BeginBlock();
DApps.Accounts.BeginTransaction();
@ -285,7 +349,13 @@ HTTPCaller.DappStaticCall = function (Params)
{
return {result:0, RetValue:"" + e};
}
return {result:1, RetValue:RetValue};
var Str = JSON.stringify({result:1, RetValue:RetValue});
if(Str.length > 16000)
{
return {result:0, RetValue:"Error result length (more 16000)"};
}
response.end(Str);
return null;
};
HTTPCaller.DappInfo = function (Params,responce,ObjectOnly)
{
@ -307,6 +377,8 @@ HTTPCaller.DappInfo = function (Params,responce,ObjectOnly)
}
catch(e)
{
if(!Account)
Account = {};
Account.SmartState = {};
}
}
@ -1391,7 +1463,7 @@ function GetFileSimple(Path)
function SaveFileSimple(Path,Str)
{
global.SendHTMLMap[Path] = undefined;
global.SendHTMLMap = {};
var Key = "GetFileSimple-" + Path;
global.SendHTMLMap[Key] = Str;
SaveToFile(Path, Str);

View File

@ -73,6 +73,12 @@ require("./log.js");
global.BufLib = require("../core/buffer");
require('../HTML/JS/sha3.js');
require('../HTML/JS/coinlib.js');
global.GetCurrentBlockNumByTime = function GetCurrentBlockNumByTime()
{
var CurTimeNum = GetCurrentTime() - 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) === "/")

View File

@ -15,89 +15,93 @@ var file_name_info = GetDataPath("info.log"), file_name_infoPrev = GetDataPath("
CheckSizeLogFile(file_name_info, file_name_infoPrev);
var file_name_log = GetDataPath("log.log"), file_name_logPrev = GetDataPath("log-prev.log");
CheckSizeLogFile(file_name_log, file_name_logPrev);
var file_name_log_web = GetDataPath("web.log"), file_name_log_webPrev = GetDataPath("web-prev.log");
CheckSizeLogFile(file_name_log_web, file_name_log_webPrev);
var StartStatTime, file_name_error = GetDataPath("err.log"), file_name_errorPrev = GetDataPath("err-prev.log");
function ToLogFile(t,e,r)
function ToLogFile(e,t,r)
{
e instanceof Error && (e = e.message + "\n" + e.stack), global.START_SERVER || (e = global.PROCESS_NAME + ": " + e), "MAIN" !== global.PROCESS_NAME && process.send ? process.send({cmd:"log",
message:e}) : (console.log(START_PORT_NUMBER + ": " + GetStrOnlyTime() + ": " + e), r || SaveToLogFileSync(t, e));
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 + ": " + GetStrOnlyTime() + ": " + t), r || SaveToLogFileSync(e, t));
};
function ToLogClient(t,e,r)
function ToLogClient(e,t,r)
{
t && (ToLogFile(file_name_log, t), e || (e = ""), ArrLogClient.push({text:GetStrOnlyTime() + " " + t, key:e, final:r}), 13 < ArrLogClient.length && ArrLogClient.shift());
e && (ToLogFile(file_name_log, e), t || (t = ""), ArrLogClient.push({text:GetStrOnlyTime() + " " + e, key:t, final:r}), 13 < ArrLogClient.length && ArrLogClient.shift());
};
CheckSizeLogFile(file_name_error, file_name_errorPrev), global.ToLog = function (t,e)
CheckSizeLogFile(file_name_error, file_name_errorPrev), global.ToLog = function (e,t)
{
void 0 === e && (e = 1), e && e > global.LOG_LEVEL || (global.ALL_LOG_TO_CLIENT ? ToLogClient(t, void 0, void 0) : ToLogFile(file_name_log,
t));
}, global.SmallAddr = function (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)
{
return t.substr(0, 5);
}, global.ToErrorTrace = function (t)
}, global.SmallAddr = function (e)
{
ToError(t + ":" + (new Error).stack);
}, global.ToLogTrace = function (t)
return e.substr(0, 5);
}, global.ToErrorTrace = function (e)
{
ToErrorTrace(t);
}, global.ToInfo = function (t)
ToError(e + ":" + (new Error).stack);
}, global.ToLogTrace = function (e)
{
ToLogFile(file_name_info, t, 1);
}, global.ToError = function (t)
ToErrorTrace(e);
}, global.ToInfo = function (e)
{
ToLogFile(file_name_error, t);
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;
function GetCurrentStatIndex()
{
var t = 2 * MAX_STAT_PERIOD + 2;
return CurStatIndex % t;
var e = 2 * MAX_STAT_PERIOD + 2;
return CurStatIndex % e;
};
function ResizeArrMax(t)
function ResizeArrMax(e)
{
for(var e = [], r = Math.trunc(t.length / 2), o = 0; o < r; o++)
e[o] = Math.max(t[2 * o], t[2 * o + 1]);
return 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(t)
function ResizeArrAvg(e)
{
for(var e = [], r = Math.trunc(t.length / 2), o = 0; o < r; o++)
e[o] = (t[2 * o] + t[2 * o + 1]) / 2;
return 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(t)
function ResizeArr(e)
{
for(var e = [], r = Math.trunc(t.length / 2), o = 0; o < r; o++)
e[o] = t[2 * o];
return e;
for(var t = [], r = Math.trunc(e.length / 2), o = 0; o < r; o++)
t[o] = e[2 * o];
return t;
};
function GetDiagramData(t,e)
function GetDiagramData(e,t)
{
var r, o = 2 * MAX_STAT_PERIOD + 2;
r = "MAX:" === e.substr(0, 4);
for(var n, a = MAX_STAT_PERIOD, l = (GetCurrentStatIndex() - a + o) % o, i = (t.Total, []), T = void 0, g = l; g < l + a; g++)
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 = t.Interval[S])
if(n = e.Interval[S])
{
var f = n[e];
void 0 !== f ? r ? i.push(f) : (void 0 !== T ? i.push(f - T) : i.push(f), T = f) : i.push(0);
var _ = n[t];
void 0 !== _ ? r ? i.push(_) : (void 0 !== T ? i.push(_ - T) : i.push(_), T = _) : i.push(0);
}
}
return i;
};
function CalcInterval(t,e,r)
function CalcInterval(e,t,r)
{
for(var o, n = 2 * MAX_STAT_PERIOD + 2, a = {}, l = (e - r + n) % n, i = t.Total, T = l; T < l + r; T++)
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 = t.Interval[g])
if(o = e.Interval[g])
break;
}
if(o)
@ -106,95 +110,98 @@ function CalcInterval(t,e,r)
return a;
};
function AddToStatContext(t,e,r)
function AddToStatContext(e,t,r)
{
void 0 === r && (r = 1);
var o = t.Total[e];
o || (o = 0), "MAX:" === e.substr(0, 4) ? o = Math.max(o, r) : o += r, t.Total[e] = o, StartStatTime || (StartStatTime = GetCurrentTime(0));
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 = GetCurrentTime(0));
};
function CopyStatInterval(t,e)
function CopyStatInterval(e,t)
{
var r = t.Interval[e];
r || (r = {}, t.Interval[e] = r);
var o = t.Total;
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(t,o)
function SaveToLogFileAsync(e,o)
{
fs.open(t, "a", void 0, function (t,r)
fs.open(e, "a", void 0, function (e,r)
{
if(t)
if(e)
console.log("Ошибка открытия лог-файла ошибок");
else
{
var e = GetStrTime() + " : " + o + "\r\n";
fs.write(r, e, null, "utf8", function (t,e)
var t = GetStrTime() + " : " + o + "\r\n";
fs.write(r, t, null, "utf8", function (e,t)
{
t ? console.log("Ошибка записи в лог-файл ошибок!") : (console.log(o), fs.close(r));
e ? console.log("Ошибка записи в лог-файл ошибок!") : fs.close(r, function (e)
{
e && console.log(e);
});
});
}
});
};
function SaveToLogFileSync(t,e)
function SaveToLogFileSync(e,t)
{
try
{
var r = GetStrTime() + " : " + e + "\r\n", o = fs.openSync(t, "a");
var r = GetStrTime() + " : " + t + "\r\n", o = fs.openSync(e, "a");
fs.writeSync(o, r, null, "utf8"), fs.closeSync(o);
}
catch(t)
catch(e)
{
console.log(t.message);
console.log(e.message);
}
};
global.PrepareStatEverySecond = function ()
{
CurStatIndex++;
var t = GetCurrentStatIndex();
CopyStatInterval(CONTEXT_STATS, t), CopyStatInterval(CONTEXT_ERRORS, t);
}, global.TO_ERROR_LOG = function (t,e,r,o,n,a)
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 = t + ":" + e;
var l = e + ":" + t;
ToError(" ==ERROR== " + l + " " + r), AddToStatContext(CONTEXT_ERRORS, l), ADD_TO_STAT("ERRORS");
}, global.HASH_RATE = 0, global.ADD_HASH_RATE = function (t)
}, global.HASH_RATE = 0, global.ADD_HASH_RATE = function (e)
{
t /= 1e6, global.HASH_RATE += t, ADD_TO_STAT("HASHRATE", t);
}, global.GET_STAT = function (t)
e /= 1e6, global.HASH_RATE += e, ADD_TO_STAT("HASHRATE", e);
}, global.GET_STAT = function (e)
{
var e = CONTEXT_STATS.Total[t];
return e || (e = 0), e;
}, global.ADD_TO_STAT_TIME = function (t,e,r)
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(e), n = 1e3 * o[0] + o[1] / 1e6;
ADD_TO_STAT(t, n);
var o = process.hrtime(t), n = 1e3 * o[0] + o[1] / 1e6;
ADD_TO_STAT(e, n);
}
}, global.ADD_TO_STAT = function (t,e,r)
}, global.ADD_TO_STAT = function (e,t,r)
{
if(global.STAT_MODE)
{
if(r && 2 !== global.STAT_MODE)
return ;
AddToStatContext(CONTEXT_STATS, t, e);
AddToStatContext(CONTEXT_STATS, e, t);
}
}, global.GET_STATDIAGRAMS = function (t)
}, global.GET_STATDIAGRAMS = function (e)
{
GetCurrentTime();
var e = GetCurrentStatIndex();
if(!t || !t.length)
var t = GetCurrentStatIndex();
if(!e || !e.length)
return [];
for(var r = [], o = 0; o < t.length; o++)
for(var r = [], o = 0; o < e.length; o++)
{
var n = t[o], a = GetDiagramData(CONTEXT_STATS, n);
r.push({name:n, maxindex:e, arr:a, starttime:StartStatTime - 0, steptime:1});
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++)
@ -209,48 +216,48 @@ global.PrepareStatEverySecond = function ()
for(var g = 0, S = 0; S < T.length; S++)
T[S] && (g += T[S]);
0 < T.length && (g /= T.length);
var f = 1;
var _ = 1;
if("MAX:" === i.name.substr(0, 4))
for(; 500 <= T.length; )
T = ResizeArrMax(T), f *= 2;
T = ResizeArrMax(T), _ *= 2;
else
for(; 500 <= T.length; )
T = ResizeArrAvg(T), f *= 2;
i.AvgValue = g, i.steptime = f, i.arr = T.slice(1);
T = ResizeArrAvg(T), _ *= 2;
i.AvgValue = g, i.steptime = _, i.arr = T.slice(1);
}
return r;
}, global.GET_STATS = function (t)
}, global.GET_STATS = function (e)
{
var e = GetCurrentTime(), r = GetCurrentStatIndex();
var t = 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:(e - StartStatTime) / 1e3, Confirmation:[]};
r, 600)}, period:(t - StartStatTime) / 1e3, Confirmation:[]};
}, global.StartCommonStat = function ()
{
for(var t in CONTEXT_STATS.Total)
for(var e in CONTEXT_STATS.Total)
return ;
ClearCommonStat();
}, global.ClearCommonStat = function ()
{
StartStatTime = void (CurStatIndex = 0), CONTEXT_STATS = {Total:{}, Interval:[]}, CONTEXT_ERRORS = {Total:{}, Interval:[]},
global.HASH_RATE = 0, SERVER.ClearStat();
}, global.ResizeArrAvg = ResizeArrAvg, global.ResizeArrMax = ResizeArrMax, DEBUG_MODE ? global.TO_DEBUG_LOG = function (t,e,r,o)
}, global.ResizeArrAvg = ResizeArrAvg, global.ResizeArrMax = ResizeArrMax, DEBUG_MODE ? global.TO_DEBUG_LOG = function (e,t,r,o)
{
DEBUG_MODE && ("rinfo" === e && (t += " from: " + r.address + ":" + r.port + " - " + o.length), ToLog(t));
} : global.TO_DEBUG_LOG = function (t,e,r,o)
DEBUG_MODE && ("rinfo" === t && (e += " from: " + r.address + ":" + r.port + " - " + o.length), ToLog(e));
} : global.TO_DEBUG_LOG = function (e,t,r,o)
{
}, global.GetStrOnlyTime = function (t)
}, global.GetStrOnlyTime = function (e)
{
if(!global.GetCurrentTime)
return ":::";
t || (t = GetCurrentTime());
var e = "" + t.getHours().toStringZ(2);
return e = (e = (e = e + ":" + t.getMinutes().toStringZ(2)) + ":" + t.getSeconds().toStringZ(2)) + "." + t.getMilliseconds().toStringZ(3);
}, global.GetStrTime = function (t)
e || (e = 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 ":::";
t || (t = GetCurrentTime());
var e = "" + t.getDate().toStringZ(2);
return e = (e = (e = (e = (e = (e = e + "." + (1 + t.getMonth()).toStringZ(2)) + "." + t.getFullYear()) + " " + t.getHours().toStringZ(2)) + ":" + t.getMinutes().toStringZ(2)) + ":" + t.getSeconds().toStringZ(2)) + "." + t.getMilliseconds().toStringZ(3);
e || (e = 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);
};

442
Source/core/rest-loader.js Normal file
View File

@ -0,0 +1,442 @@
/*
* @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://web.telegram.org/#/im?p=@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 + 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
}
ToLog("**********START REST MODE: " + this.LoadRestContext.BlockNumProof)
}
else
{
this.LoadRestContext = undefined
}
}
LoopSyncRest()
{
let Context = this.LoadRestContext;
var DeltaTime = Date.now() - Context.StartTimeHistory;
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
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++
if(Context.SendGetHeaderCount >= COUNT_NODE_PROOF * 2)
{
Context.Mode++
ToLog("Next mode: " + Context.Mode + " Send:" + Context.SendGetHeaderCount, 2)
break;
}
}
break;
case 1:
if(DeltaTime > 5000 || Context.ReceiveHeaderCount === Context.SendGetHeaderCount)
{
if(Context.ReceiveHeaderCount >= COUNT_NODE_PROOF)
{
Context.Mode++
ToLog("Next mode: " + Context.Mode + " Receive:" + Context.ReceiveHeaderCount + "/" + Context.SendGetHeaderCount, 2)
}
}
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)
{
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;
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++
ToLog("Next mode: " + Context.Mode + " SumPower:" + MaxPow, 2)
break;
case 3:
if(global.TX_PROCESS && global.TX_PROCESS.RunRPC)
{
Context.Mode++
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++
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++
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 = BufLib.GetObjectFromBuffer(Info.Data, FORMAT_BLOCK_TRANSFER, WRK_BLOCK_TRANSFER);
Info.Data = undefined
if(Data.BlockNum !== BlockProof.BlockNum || CompareArr(Data.TreeHash, BlockProof.TreeHash) !== 0)
{
ToLog("Error get proof block from " + NodeName(Item.Node), 2)
return ;
}
var TreeHash = CalcTreeHashFromArrBody(Data.BlockNum, Data.arrContent);
if(CompareArr(BlockProof.TreeHash, TreeHash) !== 0)
{
ToLog("Error TreeHash in proof block from " + NodeName(Item.Node), 2)
return ;
}
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 = BufLib.GetObjectFromBuffer(Body, FORMAT_ACCOUNT_HASH3, {})
}
catch(e)
{
ToLog("Error parsing Body[" + n + "] block proof: " + e, 2)
continue;
}
break;
}
}
if(!FindTx)
return ;
Context.TxProof = FindTx
Context.Mode++
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++
ToLog("Next mode: " + Context.Mode, 2)
break;
case 6:
break;
case 7:
if(Context.AccTaskFinished === Context.AccTaskList.length)
{
Context.Mode++
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 > 3 * 1000 && !Task.OK)
{
var Ret = this.GetNextNode(Task, "", 1);
if(Ret.Result)
{
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}, "Context":{F:function (Info)
{
if(Task.OK)
return ;
var Data = SELF.DataFromF(Info);
if(!Data.Result)
return ;
ToLog("Result GETREST Num:" + Task.StartNum + " arr=" + Data.Arr.length + " from " + NodeName(Info.Node), 2)
if(!global.TX_PROCESS || !global.TX_PROCESS.RunRPC)
return ;
global.TX_PROCESS.RunRPC("TXWriteAccArr", {StartNum:Task.StartNum, Arr:Data.Arr}, function (Err,Params)
{
Task.OK = 1
Context.AccTaskFinished++
})
}}, })
Task.Time = CurTime
break;
}
}
}
break;
case 8:
if(Context.SmartTaskFinished === Context.SmartTaskList.length)
{
Context.Mode++
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)
{
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 ;
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 ;
global.TX_PROCESS.RunRPC("TXWriteSmartArr", {StartNum:Task.StartNum, Arr:Data.Arr}, function (Err,Params)
{
Task.OK = 1
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;
ToLog(Str, 2)
var t = Math.trunc(ErrSmartNum / MAX_SMARTS_TRANSFER);
var Task = Context.SmartTaskList[t];
if(!Task)
{
ToLog("error task number: " + t)
Context.Mode = 100
}
else
{
Task.OK = 0
Context.Mode--
Context.SmartTaskFinished--
this.AddToBan(Task.Node, Str)
}
break;
}
global.TX_PROCESS.RunRPC("TXWriteAccHash", {}, function (Err,Params)
{
if(!Params)
return ;
if(CompareArr(Context.TxProof.AccHash, Params.AccHash) === 0 && CompareArr(Context.TxProof.SmartHash, Params.SmartHash) === 0)
{
Context.Mode++
ToLog("Next mode: " + Context.Mode, 2)
}
else
{
ToLog("ERROR RESTS LOAD:")
ToLog("Must AccHash:" + GetHexFromArr(Context.TxProof.AccHash))
ToLog("Must SmartHash:" + GetHexFromArr(Context.TxProof.SmartHash))
ToLog("Write AccHash:" + GetHexFromArr(Params.AccHash))
ToLog("Write SmartHash:" + GetHexFromArr(Params.SmartHash))
Context.Mode = 100
}
})
Context.Mode++
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:
ToLog("Error state!")
break;
}
}
RETBLOCKHEADER_REST(Info, CurTime)
{
var Context = this.LoadRestContext;
var BufRead = BufLib.GetReadBuffer(Info.Data);
var arr = this.GetBlockArrFromBuffer_Load(BufRead, Info);
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,\
}";
}
static
RETREST_F()
{
return global.FORMAT_REST_TRANSFER;
}
};
function CheckHashSmarts(LastSumHash)
{
DApps.Smart.Close();
var MaxNum = DApps.Smart.GetMaxNum();
var Item = DApps.Smart.DBSmart.Read(MaxNum);
if(CompareArr(Item.SumHash, LastSumHash) !== 0)
return MaxNum;
var WorkStruct = {};
for(var Num = MaxNum; Num >= 1; Num--)
{
var PrevItem = DApps.Smart.DBSmart.Read(Num - 1);
if(!PrevItem)
return Num;
var WasSumHash = Item.SumHash;
Item.SumHash = [];
var Buf = BufLib.GetBufferFromObject(Item, DApps.Smart.FORMAT_ROW, 20000, WorkStruct);
var Hash = sha3(Buf);
var SumHash = sha3arr2(PrevItem.SumHash, Hash);
if(CompareArr(SumHash, WasSumHash) !== 0)
return Num;
Item = PrevItem;
}
return 0;
};

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://web.telegram.org/#/im?p=@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);
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;

View File

@ -121,8 +121,10 @@ module.exports = class CTransport extends require("./connect")
Map["RETBLOCKHEADER"] = {Period:0}
Map["RETGETBLOCK"] = {Period:0}
Map["RETCODE"] = {Period:0}
Map["GETREST"] = {Period:1000, Hard:1}
Map["GETREST"] = {Period:1000, Hard:2, Process:global.STATIC_PROCESS}
Map["RETREST"] = {Period:0}
Map["GETSMART"] = {Period:1000, Hard:2, Process:global.STATIC_PROCESS}
Map["RETSMART"] = {Period:0}
}
if(!this.VirtualMode)
this.StartServer()
@ -249,15 +251,22 @@ module.exports = class CTransport extends require("./connect")
return ;
}
Info.Node.LastTime = CurTime - 0
var F = this[Info.Method.toUpperCase()];
if(typeof F === "function")
if(Info.Context && typeof Info.Context.F === "function")
{
F.bind(this)(Info, CurTime)
Info.Context.F(Info, CurTime)
}
else
{
TO_ERROR_LOG("TRANSPORT", 20, "Method '" + Info.Method + "' not found Socket=*" + Info.Socket.ConnectID, "node", Info.Node)
this.AddCheckErrCount(Info.Node, 1, "Method not found")
var F = this[Info.Method.toUpperCase()];
if(typeof F === "function")
{
F.bind(this)(Info, CurTime)
}
else
{
TO_ERROR_LOG("TRANSPORT", 20, "Method '" + Info.Method + "' not found Socket=*" + Info.Socket.ConnectID, "node", Info.Node)
this.AddCheckErrCount(Info.Node, 1, "Method not found")
}
}
}
GetActualNodes()

View File

@ -213,7 +213,8 @@ module.exports = class CSmartContract extends require("./block-exchange")
ToLog("Cant rewrite transactions. Very long length of the rewriting chain. Max length=" + (this.BlockNumDB - MinBlock))
return 0;
}
TX_PROCESS.Worker.send({cmd:"ReWriteDAppTransactions", StartNum:StartNum, EndNum:EndNum})
if(global.TX_PROCESS && global.TX_PROCESS.RunRPC)
global.TX_PROCESS.RunRPC("ReWriteDAppTransactions", {StartNum:StartNum, EndNum:EndNum})
return 1;
}
AddDAppTransactions(BlockNum, Arr)
@ -223,19 +224,24 @@ module.exports = class CSmartContract extends require("./block-exchange")
var BlockNumHash = BlockNum - DELTA_BLOCK_ACCOUNT_HASH;
if(BlockNumHash < 0)
return ;
var Hash = DApps.Accounts.GetHashOrUndefined(BlockNumHash);
if(Hash)
var Item = DApps.Accounts.GetAccountHashItem(BlockNumHash);
if(Item)
{
var Body = [TYPE_TRANSACTION_ACC_HASH];
WriteUintToArr(Body, BlockNumHash)
WriteArrToArr(Body, Hash, 32)
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)
}
else
{
}
}
AddTransactionOwn(Tr)
{

View File

@ -11,7 +11,7 @@
"use strict";
const fs = require('fs');
const DBRow = require("../core/db/db-row");
require('./rest_tables.js');
require('../core/rest_tables.js');
const MAX_SUM_TER = 1e9;
const MAX_SUM_CENT = 1e9;
const DBLib = require("../core/db/db");
@ -71,7 +71,15 @@ global.FORMAT_MONEY_TRANSFER_BODY3 = FORMAT_MONEY_TRANSFER3.replace("Sign:arr64,
global.FORMAT_ACCOUNT_HASH = "{\
Type:byte,\
BlockNum:uint,\
Hash:buffer32,\
AccHash:buffer32,\
}";
global.FORMAT_ACCOUNT_HASH3 = "{\
Type:byte,\
BlockNum:uint,\
AccHash:buffer32,\
AccountMax:uint,\
SmartHash:buffer32,\
SmartCount:uint,\
}";
class MerkleDBRow extends DBRow
{
@ -164,9 +172,9 @@ class AccountApp extends require("./dapp")
this.HistoryFormatArr = ["{Type:byte, BlockNum:uint32,TrNum:uint16, NextPos:uint}", "{Type:byte, BlockNum:uint32,TrNum:uint16, NextPos:uint, Direct:str1,CorrID:uint, SumCOIN:uint,SumCENT:uint32}"]
if(global.READ_ONLY_DB)
return ;
this.DBAccountsHash = new DBRow("accounts-hash2", 6 + 32 + 32 + 10, "{BlockNum:uint, Hash:hash, SumHash:hash, Reserve: arr10}",
this.DBAccountsHash = new DBRow("accounts-hash3", 6 + 32 + 32 + 32 + 6 + 6 + 14, "{BlockNum:uint, AccHash:hash, SumHash:hash, SmartHash:hash, AccountMax:uint, SmartCount:uint, Reserve: arr14}",
bReadOnly)
this.DBStateTX = new DBRow("accounts-tx", 6 + 94, "{BlockNum:uint, Reserve: arr94}", bReadOnly)
this.DBStateTX = new DBRow("accounts-tx", 6 + 6 + 88, "{BlockNum:uint, BlockNumMin:uint, Reserve: arr88}", bReadOnly)
if(global.START_SERVER)
return ;
if(!bReadOnly)
@ -379,6 +387,7 @@ class AccountApp extends require("./dapp")
}
case TYPE_TRANSACTION_ACC_HASH:
{
Result = 1
if(global.LOCAL_RUN || global.TEST_NETWORK);
else
if(BlockNum < START_BLOCK_ACCOUNT_HASH + 200000)
@ -392,8 +401,6 @@ class AccountApp extends require("./dapp")
else
{
Result = true
this.NexdDeltaAccountNum = DELTA_BLOCK_ACCOUNT_HASH
SERVER.LastNumAccountHashOK = BlockNumHash
}
break;
}
@ -485,7 +492,7 @@ class AccountApp extends require("./dapp")
}
case TYPE_TRANSACTION_ACC_HASH:
{
format = FORMAT_ACCOUNT_HASH
format = FORMAT_ACCOUNT_HASH3
break;
}
default:
@ -523,7 +530,7 @@ class AccountApp extends require("./dapp")
return 1;
try
{
var TR = BufLib.GetObjectFromBuffer(Body, FORMAT_ACCOUNT_HASH, {});
var TR = BufLib.GetObjectFromBuffer(Body, FORMAT_ACCOUNT_HASH3, {});
}
catch(e)
{
@ -532,10 +539,21 @@ class AccountApp extends require("./dapp")
if(BlockNum < START_BLOCK_ACCOUNT_HASH + 200000)
return 1;
var Item = this.GetAccountHashItem(TR.BlockNum);
if(Item)
if(Item && Item.BlockNum === TR.BlockNum)
{
if(CompareArr(Item.Hash, TR.Hash) === 0)
if(CompareArr(Item.AccHash, TR.AccHash) === 0)
{
if(TR.BlockNum >= START_BLOCK_ACCOUNT_HASH3)
{
if(CompareArr(Item.SmartHash, TR.SmartHash) === 0 && Item.AccountMax === TR.AccountMax && Item.SmartCount === TR.SmartCount)
{
return 1;
}
else
return 0;
}
return 1;
}
else
return 0;
}
@ -573,6 +591,10 @@ class AccountApp extends require("./dapp")
{
power = GetPowPower(shaarr(Body))
}
if(global.TEST_NETWORK && BlockNum >= 3290000)
{
CheckMinPower = 0
}
if(CheckMinPower && BlockNum < 19600000)
{
var MinPower;
@ -810,7 +832,11 @@ class AccountApp extends require("./dapp")
if(global.START_SERVER)
throw "DeleteAct START_SERVER";
if(BlockNumFrom > 0)
this.DBStateTX.Write({Num:0, BlockNum:BlockNumFrom - 1})
{
var StateTX = this.DBStateTX.Read(0);
StateTX.BlockNum = BlockNumFrom - 1
this.DBStateTX.Write(StateTX)
}
this.DeleteActOneDB(this.DBAct, BlockNumFrom)
this.DeleteActOneDB(this.DBActPrev, BlockNumFrom)
this.DBAccountsHash.Truncate(Math.trunc(BlockNumFrom / PERIOD_ACCOUNT_HASH))
@ -935,16 +961,10 @@ class AccountApp extends require("./dapp")
if(Data.Value.Smart)
{
Data.SmartObj = DApps.Smart.ReadSimple(Data.Value.Smart)
try
{
Data.SmartState = BufLib.GetObjectFromBuffer(Data.Value.Data, Data.SmartObj.StateFormat, {})
if(typeof Data.SmartState === "object")
Data.SmartState.Num = Num
}
catch(e)
{
if(Data.SmartObj)
Data.SmartState = this.GetSmartState(Data, Data.SmartObj.StateFormat)
else
Data.SmartState = {}
}
}
}
}
@ -1032,23 +1052,12 @@ class AccountApp extends require("./dapp")
if(Data.Value.Smart)
{
Data.SmartObj = DApps.Smart.ReadSimple(Data.Value.Smart)
try
{
Data.SmartState = BufLib.GetObjectFromBuffer(Data.Value.Data, Data.SmartObj.StateFormat, {})
if(typeof Data.SmartState === "object")
Data.SmartState.Num = num
}
catch(e)
{
if(Data.SmartObj)
Data.SmartState = this.GetSmartState(Data, Data.SmartObj.StateFormat)
else
Data.SmartState = {}
}
}
}
if(global.TEST_NETWORK)
{
var RestData = this.ReadRest(Data.Num);
Data.Arr = RestData.Arr
}
arr.push(Data)
count--
if(count < 1)
@ -1056,6 +1065,21 @@ class AccountApp extends require("./dapp")
}
return arr;
}
GetSmartState(StateData, StateFormat)
{
var SmartState;
try
{
SmartState = BufLib.GetObjectFromBuffer(StateData.Value.Data, StateFormat, {})
if(typeof SmartState === "object")
SmartState.Num = StateData.Num
}
catch(e)
{
SmartState = {}
}
return SmartState;
}
GetActsMaxNum()
{
return this.DBActPrev.GetMaxNum() + this.DBAct.GetMaxNum();
@ -1097,7 +1121,7 @@ class AccountApp extends require("./dapp")
return undefined;
var Item = this.GetAccountHashItem(BlockNum);
if(Item)
return Item.Hash;
return Item.AccHash;
else
return undefined;
}
@ -1117,7 +1141,7 @@ class AccountApp extends require("./dapp")
else
return 0;
}
CalcHash(Block)
CalcHash(Block, BlockMaxAccount)
{
if(Block.BlockNum % PERIOD_ACCOUNT_HASH !== 0)
return ;
@ -1126,9 +1150,22 @@ class AccountApp extends require("./dapp")
this.CalcMerkleTree()
}
var Hash = this.DBState.MerkleHash;
var Data = {Num:Block.BlockNum / PERIOD_ACCOUNT_HASH, BlockNum:Block.BlockNum, Hash:Hash, SumHash:Block.SumHash};
var SmartHash;
var SmartCount = DApps.Smart.GetMaxNum() + 1;
if(SmartCount > 0)
{
var MaxSmart = DApps.Smart.DBSmart.Read(SmartCount - 1);
SmartHash = MaxSmart.SumHash
}
else
{
SmartHash = []
}
var Data = {Num:Block.BlockNum / PERIOD_ACCOUNT_HASH, BlockNum:Block.BlockNum, AccHash:Hash, SumHash:Block.SumHash, AccountMax:BlockMaxAccount,
SmartHash:SmartHash, SmartCount:SmartCount};
this.DBAccountsHash.Write(Data)
this.DBAccountsHash.Truncate(Block.BlockNum / PERIOD_ACCOUNT_HASH)
return Data;
}
CalcMerkleTree(bForce)
{
@ -1223,14 +1260,10 @@ class AccountApp extends require("./dapp")
}
global.TickCounter = 0
this.DBChanges = undefined
if(BlockNum > 100)
{
var StateTX = this.DBStateTX.Read(0);
if(StateTX.BlockNum !== BlockNum - 1)
throw "ERROR SEQ STATETX";
}
this.CalcHash(Block)
this.DBStateTX.Write({Num:0, BlockNum:BlockNum})
this.CalcHash(Block, DBChanges.BlockMaxAccount)
var StateTX = this.DBStateTX.Read(0);
StateTX.BlockNum = BlockNum
this.DBStateTX.Write(StateTX)
}
CommitTransaction(BlockNum, TrNum)
{
@ -1425,8 +1458,11 @@ class AccountApp extends require("./dapp")
}
return Position;
}
GetHistory(Num, Count, StartPos)
GetHistory(Num, Count, StartPos, MinConfirm)
{
if(!MinConfirm)
MinConfirm = 0
var MaxNumBlockDB = SERVER.GetMaxNumBlockDB();
var Position = StartPos;
var FileItem = HistoryDB.OpenDBFile(FILE_NAME_HISTORY, 0);
var FD = FileItem.fd;
@ -1460,6 +1496,13 @@ class AccountApp extends require("./dapp")
var Item = BufLib.GetObjectFromBuffer(BufRead, format, WorkStructHistory);
Item.Pos = Position
Position = Item.NextPos
if(MinConfirm)
{
if(Item.BlockNum + MinConfirm > MaxNumBlockDB)
{
continue;
}
}
arr.push(Item)
}
return arr;

View File

@ -87,6 +87,7 @@ class SmartApp extends require("./dapp")
Description:str,\
Code:str,\
HTML:str,\
SumHash:hash,\
}"
this.ROW_SIZE = 2 * (1 << 13)
this.DBSmart = new DBRow("smart", this.ROW_SIZE, this.FORMAT_ROW, bReadOnly)
@ -96,11 +97,15 @@ class SmartApp extends require("./dapp")
}
Start()
{
if(this.DBSmart.GetMaxNum() + 1 >= 7)
if(this.GetMaxNum() + 1 >= 7)
return ;
this.DBSmart.Write({Num:0, ShortName:"TERA", Name:"TERA", Description:"TERA", BlockNum:0, TokenGenerate:1, Account:0, Category1:0})
this.DBSmartWrite({Num:0, ShortName:"TERA", Name:"TERA", Description:"TERA", BlockNum:0, TokenGenerate:1, Account:0, Category1:0})
for(var i = 1; i < 8; i++)
this.DBSmart.Write({Num:i, ShortName:"", Name:"", Description:"", BlockNum:0, TokenGenerate:1, Account:i, Category1:0})
this.DBSmartWrite({Num:i, ShortName:"", Name:"", Description:"", BlockNum:0, TokenGenerate:1, Account:i, Category1:0})
}
Close()
{
this.DBSmart.Close()
}
ClearDataBase()
{
@ -244,7 +249,7 @@ class SmartApp extends require("./dapp")
this.DBSmart.DeleteMap("EVAL" + Smart.Num)
return e;
}
this.DBSmart.Write(Smart)
this.DBSmartWrite(Smart)
return true;
}
CheckSignFrom(Body, TR, BlockNum, TrNum)
@ -329,7 +334,7 @@ class SmartApp extends require("./dapp")
return ResultCheck;
ContextFrom = ResultCheck
}
if(TR.Smart > DApps.Smart.GetMaxNum())
if(TR.Smart > this.GetMaxNum())
TR.Smart = 0
if(ContextFrom.FromID !== TR.Account)
return "ChangeSmart: Error account FromNum: " + TR.Account;
@ -408,7 +413,18 @@ class SmartApp extends require("./dapp")
if(Str.indexOf(Filter) < 0)
continue;
}
arr.push(Data)
var CanAdd = 1;
var DataState = DApps.Accounts.ReadState(Data.Account);
if(DataState && !global.ALL_VIEW_ROWS)
{
Data.BaseState = DApps.Accounts.GetSmartState(DataState, Data.StateFormat)
if(typeof Data.BaseState === "object" && Data.BaseState.HTMLBlock === 404)
CanAdd = 0
}
if(CanAdd)
{
arr.push(Data)
}
count--
if(count < 1)
break;
@ -419,6 +435,29 @@ class SmartApp extends require("./dapp")
{
return this.DBSmart.GetMaxNum();
}
DBSmartWrite(Item)
{
var PrevNum;
if(Item.Num === undefined)
PrevNum = this.GetMaxNum()
else
PrevNum = Item.Num - 1
Item.SumHash = []
var Buf = BufLib.GetBufferFromObject(Item, this.FORMAT_ROW, 20000, {});
var Hash = sha3(Buf);
if(PrevNum < 0)
Item.SumHash = Hash
else
{
var PrevItem = this.DBSmart.Read(PrevNum);
if(!PrevItem)
{
throw "!PrevItem of Smart num = " + PrevNum;
}
Item.SumHash = sha3arr2(PrevItem.SumHash, Hash)
}
this.DBSmart.Write(Item)
}
ReadSmart(Num)
{
Num = ParseNum(Num)
@ -554,6 +593,12 @@ function RunSmartMethod(Block,SmartOrSmartID,Account,BlockNum,TrNum,PayContext,M
if(PayContext.Value)
context.Value = {SumCOIN:PayContext.Value.SumCOIN, SumCENT:PayContext.Value.SumCENT};
}
if(BlockNum === 0)
{
context.GetBlockHeader = StaticGetBlockHeader;
context.GetBlockNumDB = StaticGetBlockNumDB;
context.GetSmart = StaticGetSmart;
}
var LocalRunContext = {Block:Block, Smart:Smart, Account:Account, BlockNum:BlockNum, TrNum:TrNum, context:context};
var RetValue;
var _RunContext = RunContext;
@ -1315,6 +1360,24 @@ function random()
RunContext.Block.Hash;
return 0;
};
function StaticGetBlockHeader(BlockNum)
{
DO(100);
return SERVER.ReadBlockHeaderDB(BlockNum);
};
function StaticGetBlockNumDB()
{
return SERVER.GetMaxNumBlockDB();
};
function StaticGetSmart(Num)
{
DO(100);
var Smart = DApps.Smart.ReadSmart(Num);
return GET_SMART(Smart);
};
ChangePrototype();
InitEval();
module.exports = SmartApp;

View File

@ -158,7 +158,9 @@ WebApi2.GetHistoryTransactions = function (Params)
{
if(!Params.Count)
Params.Count = 100;
var arr = DApps.Accounts.GetHistory(Params.AccountID, Params.Count, Params.NextPos);
if(Params.Confirm === undefined)
Params.Confirm = 8;
var arr = DApps.Accounts.GetHistory(Params.AccountID, Params.Count, Params.NextPos, Params.Confirm);
if(Params.GetTxID || Params.GetDescription)
{
for(var i = 0; i < arr.length; i++)

View File

@ -8,43 +8,3 @@
* Telegram: https://web.telegram.org/#/im?p=@terafoundation
*/
var lastcoin = 1000000000;
function show()
{
if(global.DApps && GENERATE_BLOCK_ACCOUNT)
{
var arr = DApps.Accounts.GetRowsAccounts(GENERATE_BLOCK_ACCOUNT, 1);
var Data = arr[0];
if(!Data || !Data.Value)
return ;
var sumcoin = Data.Value.SumCOIN;
var delta = sumcoin - lastcoin;
lastcoin = sumcoin;
if(delta > 200)
{
ToLog("ID:" + GENERATE_BLOCK_ACCOUNT);
if(global.COREY_WATCH_DOG === 1)
{
ToLog("Its forked restart now");
RestartNode();
}
else
if(global.COREY_WATCH_DOG === 2)
{
SERVER.FREE_ALL_MEM_CHAINS();
var Num = SERVER.BlockNumDB - 5000;
if(Num < 100)
Num = 100;
lastcoin = 1000000000;
ToLog("Its forked - truncate now from block: " + Num);
SERVER.SetTruncateBlockDB(Num);
}
}
}
};
if(global.COREY_WATCH_DOG)
{
ToLog("===START COREY_WATCH_DOG==");
setInterval(show, 35000);
}

View File

@ -73,7 +73,7 @@ process.on('error', function (err)
});
var ArrChildProcess = [];
var WebProcess = {Name:"WEB PROCESS", idInterval:0, idInterval1:0, idInterval2:0, LastAlive:Date.now(), Worker:undefined, Path:"./process/web-process.js",
OnMessage:OnMessageWeb, PeriodAlive:20 * 1000};
OnMessage:OnMessageWeb, PeriodAlive:10 * 1000};
if(global.HTTP_HOSTING_PORT && !global.NWMODE)
{
ArrChildProcess.push(WebProcess);
@ -211,105 +211,122 @@ function StartChildProcess(Item)
let ITEM = Item;
ITEM.idInterval = setInterval(function ()
{
var Delta = Date.now() - ITEM.LastAlive;
if(ITEM.Worker && Delta > ITEM.PeriodAlive)
var Delta0 = Date.now() - ITEM.LastAlive;
if(Delta0 >= 0)
{
if(ITEM.Worker)
var Delta = Date.now() - ITEM.LastAlive;
if(ITEM.Worker && Delta > ITEM.PeriodAlive)
{
ToLog("KILL PROCESS " + ITEM.Name + ": " + ITEM.Worker.pid);
try
if(ITEM.Worker)
{
process.kill(ITEM.Worker.pid, 'SIGKILL');
ToLog("KILL PROCESS " + ITEM.Name + ": " + ITEM.Worker.pid);
try
{
process.kill(ITEM.Worker.pid, 'SIGKILL');
}
catch(e)
{
return ;
}
ITEM.Worker = undefined;
}
catch(e)
{
}
ITEM.Worker = undefined;
}
}
if(!ITEM.Worker)
{
ITEM.LastAlive = (Date.now()) + ITEM.PeriodAlive * 3;
ToLog("STARTING " + ITEM.Name);
ITEM.Worker = Fork(ITEM.Path, ["READONLYDB"]);
ITEM.Worker.on('message', function (msg)
if(!ITEM.Worker)
{
if(ITEM.LastAlive < Date.now())
ITEM.LastAlive = Date.now();
switch(msg.cmd)
ITEM.LastAlive = (Date.now()) + ITEM.PeriodAlive * 3;
ToLog("STARTING " + ITEM.Name);
ITEM.Worker = Fork(ITEM.Path, ["READONLYDB"]);
ITEM.Worker.on('message', function (msg)
{
case "call":
var Err = 0;
var Ret;
try
{
Ret = global[msg.Name](msg.Params);
}
catch(e)
{
Err = 1;
Ret = "" + e;
}
if(msg.id && ITEM.Worker)
ITEM.Worker.send({cmd:"retcall", id:msg.id, Err:Err, Params:Ret});
break;
case "retcall":
var F = GlobalRunMap[msg.id];
if(F)
{
delete GlobalRunMap[msg.id];
F(msg.Err, msg.Params);
}
break;
case "log":
ToLog(msg.message);
break;
case "ToLogClient":
if(WebProcess && WebProcess.Worker)
{
WebProcess.Worker.send(msg);
}
ToLogClient(msg.Str, msg.StrKey, msg.bFinal);
break;
case "RetFindTX":
if(WebProcess && WebProcess.Worker)
{
WebProcess.Worker.send(msg);
if(msg.Web)
break;
}
ToLogClient(msg.ResultStr, msg.TX, msg.bFinal);
break;
case "online":
if(ITEM.Worker)
ToLog("RUNNING " + ITEM.Name + " : " + msg.message + " pid: " + ITEM.Worker.pid);
break;
case "WriteBodyResult":
var Block = SERVER.ReadBlockDB(msg.BlockNum);
if(Block)
{
Block.arrContentResult = msg.arrContentResult;
SERVER.WriteBodyResultDB(Block);
}
break;
default:
if(ITEM.OnMessage)
{
ITEM.OnMessage(msg);
}
break;
}
});
ITEM.Worker.on('error', function (err)
{
ToError("ERROR IN " + ITEM.Name + " Err : " + err);
ITEM.Worker = undefined;
});
ITEM.Worker.on('close', function (code)
{
ToError("CLOSE " + ITEM.Name);
ITEM.Worker = undefined;
});
if(ITEM.LastAlive < Date.now())
ITEM.LastAlive = Date.now();
switch(msg.cmd)
{
case "call":
var Err = 0;
var Ret;
try
{
if(typeof msg.Params === "object" && msg.Params.F)
{
global[msg.Name](msg.Params, function (Err,Ret)
{
if(msg.id && ITEM.Worker)
ITEM.Worker.send({cmd:"retcall", id:msg.id, Err:Err, Params:Ret});
});
break;
}
else
{
Ret = global[msg.Name](msg.Params);
}
}
catch(e)
{
Err = 1;
Ret = "" + e;
}
if(msg.id && ITEM.Worker)
ITEM.Worker.send({cmd:"retcall", id:msg.id, Err:Err, Params:Ret});
break;
case "retcall":
var F = GlobalRunMap[msg.id];
if(F)
{
delete GlobalRunMap[msg.id];
F(msg.Err, msg.Params);
}
break;
case "log":
ToLog(msg.message);
break;
case "ToLogClient":
if(WebProcess && WebProcess.Worker)
{
WebProcess.Worker.send(msg);
}
ToLogClient(msg.Str, msg.StrKey, msg.bFinal);
break;
case "RetFindTX":
if(WebProcess && WebProcess.Worker)
{
WebProcess.Worker.send(msg);
if(msg.Web)
break;
}
ToLogClient(msg.ResultStr, msg.TX, msg.bFinal);
break;
case "online":
if(ITEM.Worker)
ToLog("RUNNING " + ITEM.Name + " : " + msg.message + " pid: " + ITEM.Worker.pid);
break;
case "WriteBodyResult":
var Block = SERVER.ReadBlockDB(msg.BlockNum);
if(Block)
{
Block.arrContentResult = msg.arrContentResult;
SERVER.WriteBodyResultDB(Block);
}
break;
default:
if(ITEM.OnMessage)
{
ITEM.OnMessage(msg);
}
break;
}
});
ITEM.Worker.on('error', function (err)
{
ToError("ERROR IN " + ITEM.Name + " Err : " + err);
ITEM.Worker = undefined;
});
ITEM.Worker.on('close', function (code)
{
ToError("CLOSE " + ITEM.Name);
ITEM.Worker = undefined;
});
}
}
if(ITEM.Worker)
{
@ -724,6 +741,14 @@ function RunOnUpdate()
else
{
}
if(CurNum < 933)
{
RecreateAccountHashDB3();
}
if(CurNum < 955)
{
ReWriteDBSmartWrite();
}
ToLog("UPDATER Finish");
}
};
@ -835,6 +860,53 @@ function RecreateAccountRest1()
fs.unlinkSync(fname);
}
};
function RecreateAccountHashDB3()
{
var name = "accounts-hash2";
var fname = GetDataPath("DB/" + name);
if(fs.existsSync(fname))
{
global.UpdateMode = 1;
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 = DApps.Accounts.DBAccountsHash;
for(var num = 0; true; num++)
{
var Item = DB0.Read(num);
if(!Item)
break;
Item.AccHash = Item.Hash;
DB3.Write(Item);
}
ToLog("Finish updating " + name);
DB0.Close();
DB3.Close();
global.UpdateMode = 0;
fs.unlinkSync(fname);
}
};
function ReWriteDBSmartWrite()
{
global.UpdateMode = 1;
ToLog("Start ReWriteDBSmartWrite");
require("../core/db/db-row");
for(var num = 0; true; num++)
{
var Item = DApps.Smart.DBSmart.Read(num);
if(!Item)
break;
var Body = BufLib.GetBufferFromObject(Item, DApps.Smart.FORMAT_ROW, 20000, {});
if(Body.length > 15000)
ToLog("Smart " + Item.Num + ". " + Item.Name + " length=" + Body.length);
DApps.Smart.DBSmartWrite(Item);
}
ToLog("Finish ReWriteDBSmartWrite");
DApps.Smart.DBSmart.Close();
global.UpdateMode = 0;
};
global.TestSignLib = TestSignLib;
function TestSignLib(MaxTime)

View File

@ -12,6 +12,10 @@ global.PROCESS_NAME = "STATIC";
const crypto = require('crypto');
const fs = require('fs');
require("../core/constant");
require('../core/block-loader-const');
require('../core/rest_tables.js');
require('../dapp/accounts.js');
require('../dapp/smart.js');
global.DATA_PATH = GetNormalPathString(global.DATA_PATH);
global.CODE_PATH = GetNormalPathString(global.CODE_PATH);
require("../core/library");
@ -63,6 +67,9 @@ process.on('message', function (msg)
case "GETREST":
GETREST(msg);
break;
case "GETSMART":
GETSMART(msg);
break;
}
});
@ -101,6 +108,8 @@ setInterval(function ()
{
if(SERVER)
SERVER.ClearBufMap();
DApps.Accounts.Close();
DApps.Smart.DBSmart.Close();
global.BlockDB.CloseDBFile("block-header");
global.BlockDB.CloseDBFile("block-body");
}, 1000);
@ -115,7 +124,7 @@ function GETBLOCKHEADER(msg)
if(Foward)
{
var BlockDB = SERVER.ReadBlockHeaderDB(Data.BlockNum);
if(BlockDB && BlockDB.SumHash && CompareArr(BlockDB.SumHash, LoadHash) === 0)
if(BlockDB && BlockDB.SumHash && (CompareArr(BlockDB.SumHash, LoadHash) === 0 || IsZeroArr(LoadHash)))
{
StartNum = Data.BlockNum - BLOCK_PROCESSING_LENGTH2;
if(StartNum < 0)
@ -147,12 +156,6 @@ function GETBLOCKHEADER(msg)
var BufWrite = SERVER.BlockChainToBuf(StartNum, StartNum, BlockNum);
process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETBLOCKHEADER", Context:msg.Context, Data:BufWrite});
};
const Formats = {BLOCK_TRANSFER:"{\
BlockNum:uint,\
TreeHash:hash,\
arrContent:[tr],\
}",
WRK_BLOCK_TRANSFER:{}, };
function GETBLOCK(msg)
{
@ -164,15 +167,11 @@ function GETBLOCK(msg)
return ;
}
var BufWrite;
var BlockDB = undefined;
if(TreeHash && !IsZeroArr(TreeHash))
{
BlockDB = SERVER.ReadBlockDB(BlockNum);
}
var BlockDB = SERVER.ReadBlockDB(BlockNum);
var StrSend;
if(BlockDB && CompareArr(BlockDB.TreeHash, TreeHash) === 0)
if(BlockDB && (CompareArr(BlockDB.TreeHash, TreeHash) === 0 || IsZeroArr(TreeHash)))
{
var BufWrite = BufLib.GetBufferFromObject(BlockDB, Formats.BLOCK_TRANSFER, MAX_PACKET_LENGTH, Formats.WRK_BLOCK_TRANSFER);
var BufWrite = BufLib.GetBufferFromObject(BlockDB, FORMAT_BLOCK_TRANSFER, MAX_PACKET_LENGTH, WRK_BLOCK_TRANSFER);
StrSend = "OK";
var TreeHashTest = CalcTreeHashFromArrBody(BlockDB.BlockNum, BlockDB.arrContent);
if(CompareArr(BlockDB.TreeHash, TreeHashTest) !== 0)
@ -206,4 +205,102 @@ function GETCODE(msg)
function GETREST(msg)
{
var Data = msg.Data;
if(!Data.BlockNum)
return ;
var BlockNumRest = Data.BlockNum;
var arr = GetCurrentRestArr();
var BufLength;
var nResult = 0;
for(var i = 0; i < arr.length; i++)
{
if(arr[i] === BlockNumRest)
{
nResult = 1;
break;
}
}
var ArrRest = [];
if(nResult)
{
var WorkStruct = {};
var WorkFormat = DApps.Accounts.FORMAT_ACCOUNT_ROW;
var WorkFormatLength = DApps.Accounts.SIZE_ACCOUNT_ROW;
var Max = DApps.Accounts.DBState.GetMaxNum();
var LengthAccount = Data.Count;
if(LengthAccount > MAX_ACCOUNTS_TRANSFER)
LengthAccount = MAX_ACCOUNTS_TRANSFER;
var EndAccount = Data.AccNum + LengthAccount - 1;
if(EndAccount > Max)
EndAccount = Max;
var FindItem;
for(var Num = Data.AccNum; Num <= EndAccount; Num++)
{
FindItem = undefined;
var RestData = DApps.Accounts.ReadRest(Num);
var Data = DApps.Accounts.DBState.Read(Num);
if(!Data)
break;
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;
}
}
}
if(FindItem)
{
Data.Value = FindItem.Value;
}
else
{
if(CountZero !== RestData.Arr.length)
continue;
}
var Buf = BufLib.GetBufferFromObject(Data, WorkFormat, WorkFormatLength, WorkStruct);
ArrRest.push(Buf);
}
BufLength = 1000 + ArrRest.length * WorkFormatLength;
}
else
{
BufLength = 1000;
}
var Data2 = {Result:nResult, BlockNum:BlockNumRest, Arr:ArrRest};
var BufWrite = BufLib.GetBufferFromObject(Data2, 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 = 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 = BufLib.GetBufferFromObject(Data2, FORMAT_SMART_TRANSFER, BufLength, {});
process.send({cmd:"Send", addrStr:msg.addrStr, Method:"RETSMART", Context:msg.Context, Data:BufWrite});
};

View File

@ -62,12 +62,6 @@ process.on('message', function (msg)
case "SetSmartEvent":
global.TreeFindTX.SaveValue("Smart:" + msg.Smart, 1);
break;
case "RewriteAllTransactions":
RewriteAllTransactions(msg);
break;
case "ReWriteDAppTransactions":
ReWriteDAppTransactions(msg);
break;
case "Eval":
EvalCode(msg.Code);
break;
@ -88,7 +82,7 @@ function CheckAlive()
var Delta = Date.now() - LastAlive;
if(Delta > 100 * 1000)
{
ToLog("TX-PROCESS: ALIVE TIMEOUT Stop and exit: " + Delta + "/" + global.CHECK_STOP_CHILD_PROCESS);
ToLog("TX-PROCESS: ALIVE TIMEOUT Stop and exit: " + Delta);
process.exit(0);
return ;
}
@ -123,6 +117,7 @@ setInterval(function ()
}, 10);
var BlockTree = new STreeBuffer(30 * 1000, CompareItemHashSimple, "number");
global.bShowDetail = 0;
var MinimalValidBlock = 0;
var LastBlockNum = undefined;
function DoTXProcess()
@ -175,8 +170,12 @@ function FindMinimal()
LastBlockNum = MaxNumBlockDB - 1;
BlockTree.Clear();
}
for(var Num = LastBlockNum; Num--; Num > 0)
if(LastBlockNum < MinimalValidBlock)
LastBlockNum = MinimalValidBlock;
for(var Num = LastBlockNum; Num--; Num >= 0)
{
if(Num < MinimalValidBlock)
break;
var Block = SERVER.ReadBlockHeaderDB(Num);
if(!Block)
{
@ -198,13 +197,16 @@ function FindMinimal()
if(Item && CompareArr(Item.SumHash, Block.SumHash) === 0)
return Block;
}
RewriteAllTransactions();
Block = SERVER.ReadBlockHeaderDB(0);
if(MinimalValidBlock === 0)
RewriteAllTransactions();
Block = SERVER.ReadBlockHeaderDB(MinimalValidBlock);
return Block;
};
function IsValidSumHash(Block)
{
if(Block.BlockNum <= MinimalValidBlock + BLOCK_PROCESSING_LENGTH2)
return 1;
if(Block.BlockNum < 16)
return 1;
if(IsZeroArr(Block.SumHash))
@ -233,11 +235,12 @@ function InitTXProcess()
LastBlockNum = Item.BlockNum;
}
}
ToLog("DETECT NEW VER on BlockNum=" + LastBlockNum);
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum});
ToLog("DETECT NEW VER on BlockNum=" + LastBlockNum, 2);
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum, BlockNumMin:MinimalValidBlock});
}
StateTX = DApps.Accounts.DBStateTX.Read(0);
LastBlockNum = StateTX.BlockNum;
MinimalValidBlock = StateTX.BlockNumMin;
LastBlockNum = PERIOD_ACCOUNT_HASH * Math.trunc(LastBlockNum / PERIOD_ACCOUNT_HASH);
if(LastBlockNum > 100)
{
@ -246,12 +249,30 @@ function InitTXProcess()
if(LastBlockNum <= 0)
RewriteAllTransactions();
else
ToLog("Start NUM = " + LastBlockNum);
ToLog("Start NUM = " + LastBlockNum, 2);
DApps.Accounts.CalcMerkleTree();
};
global.ClearDataBase = ClearDataBase;
function ClearDataBase()
{
MinimalValidBlock = 0;
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
LastBlockNum = 0;
BlockTree.Clear();
};
global.RewriteAllTransactions = RewriteAllTransactions;
function RewriteAllTransactions()
{
if(MinimalValidBlock > 0)
{
ToLog("*************Cant run RewriteAllTransactions, MinimalValidBlock:" + MinimalValidBlock, 2);
return ;
}
ToLog("*************RewriteAllTransactions");
for(var key in DApps)
{
@ -259,19 +280,80 @@ function RewriteAllTransactions()
}
LastBlockNum = 0;
BlockTree.Clear();
ToLog("Start num = " + LastBlockNum);
ToLog("Start num = " + LastBlockNum, 2);
};
global.ReWriteDAppTransactions = ReWriteDAppTransactions;
function ReWriteDAppTransactions(msg)
function ReWriteDAppTransactions(Params)
{
var StartNum = msg.StartNum;
var EndNum = msg.EndNum;
var StartNum = Params.StartNum;
var EndNum = Params.EndNum;
ToLog("ReWriteDAppTransactions: " + StartNum + " - " + EndNum);
BlockTree.Clear();
if(StartNum < LastBlockNum)
LastBlockNum = StartNum;
ToLog("Start num = " + LastBlockNum);
ToLog("Start num = " + LastBlockNum, 2);
};
function TXPrepareLoadRest(BlockNum)
{
MinimalValidBlock = BlockNum;
ToLog("*************TXPrepareLoadRest:" + BlockNum, 2);
for(var key in DApps)
{
DApps[key].ClearDataBase();
}
LastBlockNum = BlockNum;
BlockTree.Clear();
DApps.Accounts.DBStateTX.Write({Num:0, BlockNum:LastBlockNum, BlockNumMin:LastBlockNum});
};
global.TXPrepareLoadRest = TXPrepareLoadRest;
function TXWriteAccArr(Params)
{
var WorkStruct = {};
var WorkFormat = DApps.Accounts.FORMAT_ACCOUNT_ROW;
ToLog("Write accounts: " + Params.StartNum + "-" + Params.Arr.length, 2);
for(var i = 0; i < Params.Arr.length; i++)
{
var Data = BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct);
Data.Num = Params.StartNum + i;
DApps.Accounts._DBStateWrite(Data, MinimalValidBlock);
}
};
global.TXWriteAccArr = TXWriteAccArr;
function TXWriteSmartArr(Params)
{
var WorkStruct = {};
var WorkFormat = DApps.Smart.FORMAT_ROW;
ToLog("Write smarts: " + Params.StartNum + "-" + Params.Arr.length, 2);
for(var i = 0; i < Params.Arr.length; i++)
{
var Data = BufLib.GetObjectFromBuffer(Params.Arr[i], WorkFormat, WorkStruct);
Data.Num = Params.StartNum + i;
DApps.Smart.DBSmart.Write(Data);
}
};
global.TXWriteSmartArr = TXWriteSmartArr;
function TXWriteAccHash()
{
ToLog("Start TXWriteAccHash", 2);
for(var num = 0; true; num++)
{
var Item = DApps.Smart.DBSmart.Read(num);
if(!Item)
break;
var Body = BufLib.GetBufferFromObject(Item, DApps.Smart.FORMAT_ROW, 20000, {});
DApps.Smart.DBSmartWrite(Item);
}
var Block = {BlockNum:MinimalValidBlock, SumHash:[]};
var MaxAccount = DApps.Accounts.GetMaxAccount();
var DataHash = DApps.Accounts.CalcHash(Block, MaxAccount);
return DataHash;
};
global.TXWriteAccHash = TXWriteAccHash;
global.EvalCode = function (Code)
{
var Result;

View File

@ -41,7 +41,7 @@ process.on('message', function (msg)
case "ALive":
break;
case "Exit":
process.exit(0);
Exit();
break;
case "call":
var Err = 0;
@ -103,6 +103,19 @@ process.on('message', function (msg)
}
}
});
var RedirectServer;
var HostingServer;
function Exit()
{
ToLogWeb("=Exit1=");
if(RedirectServer)
RedirectServer.close();
if(HostingServer)
HostingServer.close();
ToLogWeb("=Exit2=");
process.exit(0);
};
function CheckAlive()
{
@ -111,8 +124,7 @@ function CheckAlive()
var Delta = Date.now() - LastAlive;
if(Delta > CHECK_STOP_CHILD_PROCESS)
{
ToLog("HOSTING: ALIVE TIMEOUT Stop and exit: " + Delta + "/" + global.CHECK_STOP_CHILD_PROCESS, 0);
process.exit(0);
Exit();
return ;
}
};
@ -144,7 +156,6 @@ require("../core/html-server");
require("../core/transaction-validator");
global.STAT_MODE = 1;
setInterval(PrepareStatEverySecond, 1000);
var HostingServer;
if(global.HTTPS_HOSTING_DOMAIN)
{
var file_sert = GetDataPath("sertif.lst");
@ -152,15 +163,20 @@ if(global.HTTPS_HOSTING_DOMAIN)
var greenlock = require('greenlock').create({version:'draft-12', server:'https://acme-v02.api.letsencrypt.org/directory', configDir:GetDataPath('tmp'),
});
var redir = require('redirect-https')();
require('http').createServer(greenlock.middleware(redir)).listen(80);
RedirectServer = require('http').createServer(greenlock.middleware(redir));
RedirectServer.on('error', function (err)
{
ToError('RedirectServer: ' + err.code);
});
RedirectServer.listen(80);
var GetNewSert = 1;
if(fs.existsSync(file_sert))
{
var certs = LoadParams(file_sert, {});
var Delta = certs.expiresAt - Date.now();
if(Delta > 7 * 86000 * 1000)
if(Delta >= 10 * 24 * 3600 * 1000)
{
ToLog("USE OLD SERT. ExpiresAt: " + new Date(certs.expiresAt));
ToLog("USE EXIST SERT. ExpiresAt: " + new Date(certs.expiresAt));
GetNewSert = 0;
var tlsOptions = {key:certs.privkey, cert:certs.cert + '\r\n' + certs.chain};
HostingServer = require('https').createServer(tlsOptions, MainHTTPFunction);
@ -191,12 +207,15 @@ else
function MainHTTPFunction(request,response)
{
if(!request.headers)
return ;
if(!request.socket || !request.socket.remoteAddress)
return ;
SetSafeResponce(response);
var DataURL = url.parse(request.url);
var Params = querystring.parse(DataURL.query);
var Path = querystring.unescape(DataURL.pathname);
ToLogWeb("Get Path:" + Path);
var Type = request.method;
if(Type === "POST")
{
@ -252,10 +271,11 @@ function RunListenServer()
ToLogClient('Port ' + global.HTTP_HOSTING_PORT + ' in use, retrying...');
if(HostingServer.Server)
HostingServer.Server.close();
setTimeout(function ()
{
RunListenServer();
}, TimeToRerun);
if(!bWasRun)
setTimeout(function ()
{
RunListenServer();
}, TimeToRerun);
return ;
}
ToError("H##6");
@ -297,6 +317,7 @@ WalletFileMap["wallet.css"] = 1;
WalletFileMap["history.html"] = 1;
WalletFileMap["blockviewer.html"] = 1;
WalletFileMap["web-wallet.html"] = 1;
WalletFileMap["web-wallet-cn.html"] = 1;
global.WebApi2 = {};
global.HostingCaller = {};
@ -655,11 +676,11 @@ HostingCaller.DappSmartHTMLFile = function (Params)
return {result:0};
return HTTPCaller.DappSmartHTMLFile(Params);
};
HostingCaller.DappBlockFile = function (Params)
HostingCaller.DappBlockFile = function (Params,responce)
{
if(typeof Params !== "object")
return {result:0};
return HTTPCaller.DappBlockFile(Params);
return HTTPCaller.DappBlockFile(Params, responce);
};
HostingCaller.DappInfo = function (Params)
{
@ -749,11 +770,11 @@ HostingCaller.DappTransactionList = function (Params)
var arr = SERVER.GetTrRows(ParseNum(Params.BlockNum), ParseNum(Params.StartNum), ParseNum(Params.CountNum));
return {arr:arr, result:1};
};
HostingCaller.DappStaticCall = function (Params)
HostingCaller.DappStaticCall = function (Params,response)
{
if(typeof Params !== "object")
return {result:0};
return HTTPCaller.DappStaticCall(Params);
return HTTPCaller.DappStaticCall(Params, response);
};
HostingCaller.GetHistoryTransactions = function (Params)
{
@ -792,12 +813,13 @@ setInterval(function ()
setInterval(function ()
{
var MaxNumBlockDB = SERVER.GetMaxNumBlockDB();
var arr = SERVER.GetStatBlockchain("POWER_BLOCKCHAIN", 100);
var HASHARATE_BLOCK_LENGTH = 200;
var arr = SERVER.GetStatBlockchain("POWER_BLOCKCHAIN", HASHARATE_BLOCK_LENGTH);
if(arr.length)
{
var SumPow = 0;
var Count = 0;
for(var i = arr.length - 100; i < arr.length; i++)
for(var i = arr.length - HASHARATE_BLOCK_LENGTH; i < arr.length; i++)
if(arr[i])
{
SumPow += arr[i];
@ -811,8 +833,7 @@ setInterval(function ()
if(MaxNumBlockDB > Count)
{
var StartNum = MaxNumBlockDB - Count;
var BufWrite = SERVER.BlockChainToBuf(StartNum, StartNum, MaxNumBlockDB);
NodeBlockChain = BufWrite;
NodeBlockChain = SERVER.BlockChainToBuf(StartNum, StartNum, MaxNumBlockDB);
}
}, 1000);
require("./api-exchange.js");
@ -823,3 +844,12 @@ try
catch(e)
{
}
global.LoadBlockFromNetwork = function (Params,F)
{
ToLog("RUN: LoadBlockFromNetwork:" + Params.BlockNum);
process.RunRPC("LoadBlockFromNetwork", {BlockNum:Params.BlockNum, F:1}, function (Err,Block)
{
ToLog("RETURN: LoadBlockFromNetwork: " + Params.BlockNum);
F(Err, Block);
});
};