Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d03cd9e9f6 | ||
|
|
f700c3a1c7 | ||
|
|
f564e7efa1 | ||
|
|
55c2ccc12c | ||
|
|
0d181f5512 | ||
|
|
cf6811d5c0 | ||
|
|
d3d20f596b | ||
|
|
54c9d063be | ||
|
|
be078f910f | ||
|
|
6252d4e3fe | ||
|
|
90fb711d2a | ||
|
|
271815e731 | ||
|
|
1a8b491fba | ||
|
|
d6235f4121 | ||
|
|
dacd9420a1 | ||
|
|
7e11df5a28 | ||
|
|
88f50fcae1 | ||
|
|
3251f98ebf | ||
|
|
98dba661b1 | ||
|
|
ca9e95e7af | ||
|
|
5bbbca15a9 | ||
|
|
4c79b7f460 | ||
|
|
5906372fc0 | ||
|
|
30c76cab5c | ||
|
|
e70d422da5 | ||
|
|
754017f634 | ||
|
|
4aeff314bb | ||
|
|
c25ccfe064 | ||
|
|
5fbb3c3ac2 | ||
|
|
d6c6d3420e | ||
|
|
e389988bda | ||
|
|
c8a8d3b9d0 | ||
|
|
3f42a53991 | ||
|
|
6383aade6e | ||
|
|
17acd5830e | ||
|
|
f33402382b | ||
|
|
3ddc0dd90e | ||
|
|
33587258a8 | ||
|
|
49df2cf71f | ||
|
|
975e602088 | ||
|
|
6483f377b5 | ||
|
|
843d1d0fef | ||
|
|
91f6e1f5d4 | ||
|
|
33aa9cb6c5 | ||
|
|
29c27c426e | ||
|
|
2202811745 | ||
|
|
30f35944ea | ||
|
|
7146cfd3c0 | ||
|
|
024042abab | ||
|
|
0b73adb3d8 | ||
|
|
a03484adee | ||
|
|
99f17a3e7d | ||
|
|
3549da461d | ||
|
|
616dde11ea | ||
|
|
31f5ff0bd1 | ||
|
|
3cad1162ef | ||
|
|
7a83f1ab10 | ||
|
|
b974dc4c9a | ||
|
|
55a1dc750c | ||
|
|
4b47d0d88e | ||
|
|
6a6005ca4c | ||
|
|
9dd74285f7 | ||
|
|
788f438114 | ||
|
|
f3e430fee5 | ||
|
|
faf8cc05f7 | ||
|
|
de732ee7f9 | ||
|
|
74190d40ba | ||
|
|
65e801989d | ||
|
|
d688423d3e | ||
|
|
ffc87d69bf | ||
|
|
2a49e6c70a | ||
|
|
6c8bc7b97c | ||
|
|
7efb4df493 | ||
|
|
beff53e938 | ||
|
|
5ca54479a7 | ||
|
|
547cac4afb | ||
|
|
bc9c945646 | ||
|
|
8be4270e16 | ||
|
|
971c385042 | ||
|
|
984aedc940 | ||
|
|
e59bb416b4 | ||
|
|
57d2257c43 | ||
|
|
8c32d1c71b | ||
|
|
b5110bf01f | ||
|
|
0567899edd | ||
|
|
66b1221e22 | ||
|
|
9e9c12fbbb | ||
|
|
c5002508d6 | ||
|
|
fbc48921f3 | ||
|
|
07dcebd895 | ||
|
|
6651ff54fc | ||
|
|
38745111ef | ||
|
|
c83895d384 | ||
|
|
62cc290b50 | ||
|
|
dab6648ae8 | ||
|
|
5c476be954 | ||
|
|
0d5f79fc20 | ||
|
|
5fc167cfbf | ||
|
|
5f4b6d9d51 |
25
.travis.yml
Normal file
25
.travis.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
dist: trusty
|
||||||
|
language: php
|
||||||
|
|
||||||
|
php:
|
||||||
|
- 7.2
|
||||||
|
- nightly
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- php: nightly
|
||||||
|
|
||||||
|
# This triggers builds to run on the new TravisCI infrastructure.
|
||||||
|
# See: https://docs.travis-ci.com/user/reference/trusty#Container-based-with-sudo%3A-false
|
||||||
|
sudo: false
|
||||||
|
|
||||||
|
## Cache composer
|
||||||
|
cache:
|
||||||
|
directories:
|
||||||
|
- $HOME/.composer/cache
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- travis_retry composer update --no-interaction --prefer-dist
|
||||||
|
|
||||||
|
script:
|
||||||
|
- vendor/bin/phpcs -l --standard=psr2 . include
|
||||||
@@ -5,11 +5,11 @@ The Arionum (ARO) cryptocurrency node.
|
|||||||
## Install
|
## Install
|
||||||
|
|
||||||
**Hardware Requirements:**
|
**Hardware Requirements:**
|
||||||
|
```
|
||||||
2GB RAM
|
2GB RAM
|
||||||
1 CPU Core
|
1 CPU Core
|
||||||
50GB DISK
|
50GB DISK
|
||||||
|
```
|
||||||
**Requirements:**
|
**Requirements:**
|
||||||
|
|
||||||
- PHP 7.2
|
- PHP 7.2
|
||||||
@@ -19,7 +19,7 @@ The Arionum (ARO) cryptocurrency node.
|
|||||||
- MySQL/MariaDB
|
- MySQL/MariaDB
|
||||||
|
|
||||||
1. Install MySQL or MariaDB and create a database and a user.
|
1. Install MySQL or MariaDB and create a database and a user.
|
||||||
2. Edit `include/config.inc.php` and set the DB login data
|
2. Rename `include/config-sample.inc.php` to `include/config.inc.php` and set the DB login data
|
||||||
3. Change permissions to tmp and `tmp/db-update` to 777 (`chmod 777 tmp -R`)
|
3. Change permissions to tmp and `tmp/db-update` to 777 (`chmod 777 tmp -R`)
|
||||||
4. Access the http://ip-or-domain and refresh once
|
4. Access the http://ip-or-domain and refresh once
|
||||||
|
|
||||||
|
|||||||
103
api.php
103
api.php
@@ -23,6 +23,8 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @api {get} /api.php 01. Basic Information
|
* @api {get} /api.php 01. Basic Information
|
||||||
@@ -65,7 +67,9 @@ OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
require_once("include/init.inc.php");
|
use Arionum\Blacklist;
|
||||||
|
|
||||||
|
require_once __DIR__.'/include/init.inc.php';
|
||||||
error_reporting(0);
|
error_reporting(0);
|
||||||
$ip = san_ip($_SERVER['REMOTE_ADDR']);
|
$ip = san_ip($_SERVER['REMOTE_ADDR']);
|
||||||
$ip = filter_var($ip, FILTER_VALIDATE_IP);
|
$ip = filter_var($ip, FILTER_VALIDATE_IP);
|
||||||
@@ -160,6 +164,7 @@ if ($q == "getAddress") {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$account = $data['account'];
|
$account = $data['account'];
|
||||||
|
$public_key = san($data['public_key'] ?? '');
|
||||||
if (!empty($public_key) && strlen($public_key) < 32) {
|
if (!empty($public_key) && strlen($public_key) < 32) {
|
||||||
api_err("Invalid public key");
|
api_err("Invalid public key");
|
||||||
}
|
}
|
||||||
@@ -199,6 +204,7 @@ if ($q == "getAddress") {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
$account = san($data['account']);
|
$account = san($data['account']);
|
||||||
|
$public_key = san($data['public_key'] ?? '');
|
||||||
if (!empty($public_key) && strlen($public_key) < 32) {
|
if (!empty($public_key) && strlen($public_key) < 32) {
|
||||||
api_err("Invalid public key");
|
api_err("Invalid public key");
|
||||||
}
|
}
|
||||||
@@ -428,6 +434,11 @@ if ($q == "getAddress") {
|
|||||||
if (!$acc->valid_key($public_key)) {
|
if (!$acc->valid_key($public_key)) {
|
||||||
api_err("Invalid public key");
|
api_err("Invalid public key");
|
||||||
}
|
}
|
||||||
|
if ($_config['use_official_blacklist']!==false) {
|
||||||
|
if (Blacklist::checkPublicKey($public_key)) {
|
||||||
|
api_err("Blacklisted account");
|
||||||
|
}
|
||||||
|
}
|
||||||
$private_key = san($data['private_key']);
|
$private_key = san($data['private_key']);
|
||||||
if (!$acc->valid_key($private_key)) {
|
if (!$acc->valid_key($private_key)) {
|
||||||
api_err("Invalid private key");
|
api_err("Invalid private key");
|
||||||
@@ -528,6 +539,7 @@ if ($q == "getAddress") {
|
|||||||
$transaction['id'] = $hash;
|
$transaction['id'] = $hash;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!$trx->check($transaction)) {
|
if (!$trx->check($transaction)) {
|
||||||
api_err("Transaction signature failed");
|
api_err("Transaction signature failed");
|
||||||
}
|
}
|
||||||
@@ -559,6 +571,7 @@ if ($q == "getAddress") {
|
|||||||
|
|
||||||
|
|
||||||
$trx->add_mempool($transaction, "local");
|
$trx->add_mempool($transaction, "local");
|
||||||
|
$hash=escapeshellarg(san($hash));
|
||||||
system("php propagate.php transaction $hash > /dev/null 2>&1 &");
|
system("php propagate.php transaction $hash > /dev/null 2>&1 &");
|
||||||
api_echo($hash);
|
api_echo($hash);
|
||||||
} elseif ($q == "mempoolSize") {
|
} elseif ($q == "mempoolSize") {
|
||||||
@@ -638,11 +651,12 @@ if ($q == "getAddress") {
|
|||||||
* @apiSuccess {boolean} data masternode date
|
* @apiSuccess {boolean} data masternode date
|
||||||
*/
|
*/
|
||||||
|
|
||||||
$res=$db->run("SELECT * FROM masternode");
|
$res=$db->run("SELECT * FROM masternode ORDER by public_key ASC");
|
||||||
api_echo($res);
|
|
||||||
|
api_echo(["masternodes"=>$res, "hash"=>md5(json_encode($res))]);
|
||||||
} elseif ($q == "getAlias") {
|
} elseif ($q == "getAlias") {
|
||||||
/**
|
/**
|
||||||
* @api {get} /api.php?q=getAlias 189. getAlias
|
* @api {get} /api.php?q=getAlias 19. getAlias
|
||||||
* @apiName getAlias
|
* @apiName getAlias
|
||||||
* @apiGroup API
|
* @apiGroup API
|
||||||
* @apiDescription Returns the alias of an account
|
* @apiDescription Returns the alias of an account
|
||||||
@@ -669,6 +683,87 @@ if ($q == "getAddress") {
|
|||||||
$account = san($account);
|
$account = san($account);
|
||||||
|
|
||||||
api_echo($acc->account2alias($account));
|
api_echo($acc->account2alias($account));
|
||||||
|
} elseif ($q === 'sanity') {
|
||||||
|
/**
|
||||||
|
* @api {get} /api.php?q=sanity 20. sanity
|
||||||
|
* @apiName sanity
|
||||||
|
* @apiGroup API
|
||||||
|
* @apiDescription Returns details about the node's sanity process.
|
||||||
|
*
|
||||||
|
* @apiSuccess {object} data A collection of data about the sanity process.
|
||||||
|
* @apiSuccess {boolean} data.sanity_running Whether the sanity process is currently running.
|
||||||
|
* @apiSuccess {number} data.last_sanity The timestamp for the last time the sanity process was run.
|
||||||
|
* @apiSuccess {boolean} data.sanity_sync Whether the sanity process is currently synchronising.
|
||||||
|
*/
|
||||||
|
$sanity = file_exists(__DIR__.'/tmp/sanity-lock');
|
||||||
|
|
||||||
|
$lastSanity = (int)$db->single("SELECT val FROM config WHERE cfg='sanity_last'");
|
||||||
|
$sanitySync = (bool)$db->single("SELECT val FROM config WHERE cfg='sanity_sync'");
|
||||||
|
api_echo(['sanity_running' => $sanity, 'last_sanity' => $lastSanity, 'sanity_sync' => $sanitySync]);
|
||||||
|
} elseif ($q === 'node-info') {
|
||||||
|
/**
|
||||||
|
* @api {get} /api.php?q=node-info 21. node-info
|
||||||
|
* @apiName node-info
|
||||||
|
* @apiGroup API
|
||||||
|
* @apiDescription Returns details about the node.
|
||||||
|
*
|
||||||
|
* @apiSuccess {object} data A collection of data about the node.
|
||||||
|
* @apiSuccess {string} data.hostname The hostname of the node.
|
||||||
|
* @apiSuccess {string} data.version The current version of the node.
|
||||||
|
* @apiSuccess {string} data.dbversion The database schema version for the node.
|
||||||
|
* @apiSuccess {number} data.accounts The number of accounts known by the node.
|
||||||
|
* @apiSuccess {number} data.transactions The number of transactions known by the node.
|
||||||
|
* @apiSuccess {number} data.mempool The number of transactions in the mempool.
|
||||||
|
* @apiSuccess {number} data.masternodes The number of masternodes known by the node.
|
||||||
|
* @apiSuccess {number} data.peers The number of valid peers.
|
||||||
|
*/
|
||||||
|
$dbVersion = $db->single("SELECT val FROM config WHERE cfg='dbversion'");
|
||||||
|
$hostname = $db->single("SELECT val FROM config WHERE cfg='hostname'");
|
||||||
|
$acc = $db->single("SELECT COUNT(1) FROM accounts");
|
||||||
|
$tr = $db->single("SELECT COUNT(1) FROM transactions");
|
||||||
|
$masternodes = $db->single("SELECT COUNT(1) FROM masternode");
|
||||||
|
$mempool = $db->single("SELECT COUNT(1) FROM mempool");
|
||||||
|
$peers = $db->single("SELECT COUNT(1) FROM peers WHERE blacklisted<UNIX_TIMESTAMP()");
|
||||||
|
api_echo([
|
||||||
|
'hostname' => $hostname,
|
||||||
|
'version' => VERSION,
|
||||||
|
'dbversion' => $dbVersion,
|
||||||
|
'accounts' => $acc,
|
||||||
|
'transactions' => $tr,
|
||||||
|
'mempool' => $mempool,
|
||||||
|
'masternodes' => $masternodes,
|
||||||
|
'peers' => $peers
|
||||||
|
]);
|
||||||
|
} elseif ($q === 'checkAddress') {
|
||||||
|
/**
|
||||||
|
* @api {get} /api.php?q=checkAddress 22. checkAddress
|
||||||
|
* @apiName checkAddress
|
||||||
|
* @apiGroup API
|
||||||
|
* @apiDescription Checks the validity of an address.
|
||||||
|
*
|
||||||
|
* @apiParam {string} account Account id / address
|
||||||
|
* @apiParam {string} [public_key] Public key
|
||||||
|
*
|
||||||
|
* @apiSuccess {boolean} data True if the address is valid, false otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$address=$data['account'];
|
||||||
|
$public_key=$data['public_key'];
|
||||||
|
$acc = new Account();
|
||||||
|
if (!$acc->valid($address)) {
|
||||||
|
api_err(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dst_b = base58_decode($address);
|
||||||
|
if (strlen($dst_b) != 64) {
|
||||||
|
api_err(false);
|
||||||
|
}
|
||||||
|
if (!empty($public_key)) {
|
||||||
|
if($acc->get_address($public_key)!=$address){
|
||||||
|
api_err(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
api_echo(true);
|
||||||
} else {
|
} else {
|
||||||
api_err("Invalid request");
|
api_err("Invalid request");
|
||||||
}
|
}
|
||||||
|
|||||||
171
doc/api_data.js
171
doc/api_data.js
@@ -101,6 +101,50 @@ define({ "api": [
|
|||||||
"filename": "./api.php",
|
"filename": "./api.php",
|
||||||
"groupTitle": "API"
|
"groupTitle": "API"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get",
|
||||||
|
"url": "/api.php?q=checkAddress",
|
||||||
|
"title": "22. checkAddress",
|
||||||
|
"name": "checkAddress",
|
||||||
|
"group": "API",
|
||||||
|
"description": "<p>Checks the validity of an address.</p>",
|
||||||
|
"parameter": {
|
||||||
|
"fields": {
|
||||||
|
"Parameter": [
|
||||||
|
{
|
||||||
|
"group": "Parameter",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "account",
|
||||||
|
"description": "<p>Account id / address</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Parameter",
|
||||||
|
"type": "string",
|
||||||
|
"optional": true,
|
||||||
|
"field": "public_key",
|
||||||
|
"description": "<p>Public key</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"fields": {
|
||||||
|
"Success 200": [
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "boolean",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data",
|
||||||
|
"description": "<p>True if the address is valid, false otherwise.</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"filename": "./api.php",
|
||||||
|
"groupTitle": "API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=checkSignature",
|
"url": "/api.php?q=checkSignature",
|
||||||
@@ -303,7 +347,7 @@ define({ "api": [
|
|||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=getAlias",
|
"url": "/api.php?q=getAlias",
|
||||||
"title": "189. getAlias",
|
"title": "19. getAlias",
|
||||||
"name": "getAlias",
|
"name": "getAlias",
|
||||||
"group": "API",
|
"group": "API",
|
||||||
"description": "<p>Returns the alias of an account</p>",
|
"description": "<p>Returns the alias of an account</p>",
|
||||||
@@ -1015,6 +1059,86 @@ define({ "api": [
|
|||||||
"filename": "./api.php",
|
"filename": "./api.php",
|
||||||
"groupTitle": "API"
|
"groupTitle": "API"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get",
|
||||||
|
"url": "/api.php?q=node-info",
|
||||||
|
"title": "21. node-info",
|
||||||
|
"name": "node_info",
|
||||||
|
"group": "API",
|
||||||
|
"description": "<p>Returns details about the node.</p>",
|
||||||
|
"success": {
|
||||||
|
"fields": {
|
||||||
|
"Success 200": [
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "object",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data",
|
||||||
|
"description": "<p>A collection of data about the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.hostname",
|
||||||
|
"description": "<p>The hostname of the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.version",
|
||||||
|
"description": "<p>The current version of the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.dbversion",
|
||||||
|
"description": "<p>The database schema version for the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.accounts",
|
||||||
|
"description": "<p>The number of accounts known by the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.transactions",
|
||||||
|
"description": "<p>The number of transactions known by the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.mempool",
|
||||||
|
"description": "<p>The number of transactions in the mempool.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.masternodes",
|
||||||
|
"description": "<p>The number of masternodes known by the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.peers",
|
||||||
|
"description": "<p>The number of valid peers.</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"filename": "./api.php",
|
||||||
|
"groupTitle": "API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=randomNumber",
|
"url": "/api.php?q=randomNumber",
|
||||||
@@ -1073,6 +1197,51 @@ define({ "api": [
|
|||||||
"filename": "./api.php",
|
"filename": "./api.php",
|
||||||
"groupTitle": "API"
|
"groupTitle": "API"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get",
|
||||||
|
"url": "/api.php?q=sanity",
|
||||||
|
"title": "20. sanity",
|
||||||
|
"name": "sanity",
|
||||||
|
"group": "API",
|
||||||
|
"description": "<p>Returns details about the node's sanity process.</p>",
|
||||||
|
"success": {
|
||||||
|
"fields": {
|
||||||
|
"Success 200": [
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "object",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data",
|
||||||
|
"description": "<p>A collection of data about the sanity process.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "boolean",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.sanity_running",
|
||||||
|
"description": "<p>Whether the sanity process is currently running.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.last_sanity",
|
||||||
|
"description": "<p>The timestamp for the last time the sanity process was run.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "boolean",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.sanity_sync",
|
||||||
|
"description": "<p>Whether the sanity process is currently synchronising.</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"filename": "./api.php",
|
||||||
|
"groupTitle": "API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=send",
|
"url": "/api.php?q=send",
|
||||||
|
|||||||
@@ -101,6 +101,50 @@
|
|||||||
"filename": "./api.php",
|
"filename": "./api.php",
|
||||||
"groupTitle": "API"
|
"groupTitle": "API"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get",
|
||||||
|
"url": "/api.php?q=checkAddress",
|
||||||
|
"title": "22. checkAddress",
|
||||||
|
"name": "checkAddress",
|
||||||
|
"group": "API",
|
||||||
|
"description": "<p>Checks the validity of an address.</p>",
|
||||||
|
"parameter": {
|
||||||
|
"fields": {
|
||||||
|
"Parameter": [
|
||||||
|
{
|
||||||
|
"group": "Parameter",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "account",
|
||||||
|
"description": "<p>Account id / address</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Parameter",
|
||||||
|
"type": "string",
|
||||||
|
"optional": true,
|
||||||
|
"field": "public_key",
|
||||||
|
"description": "<p>Public key</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"success": {
|
||||||
|
"fields": {
|
||||||
|
"Success 200": [
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "boolean",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data",
|
||||||
|
"description": "<p>True if the address is valid, false otherwise.</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"filename": "./api.php",
|
||||||
|
"groupTitle": "API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=checkSignature",
|
"url": "/api.php?q=checkSignature",
|
||||||
@@ -303,7 +347,7 @@
|
|||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=getAlias",
|
"url": "/api.php?q=getAlias",
|
||||||
"title": "189. getAlias",
|
"title": "19. getAlias",
|
||||||
"name": "getAlias",
|
"name": "getAlias",
|
||||||
"group": "API",
|
"group": "API",
|
||||||
"description": "<p>Returns the alias of an account</p>",
|
"description": "<p>Returns the alias of an account</p>",
|
||||||
@@ -1015,6 +1059,86 @@
|
|||||||
"filename": "./api.php",
|
"filename": "./api.php",
|
||||||
"groupTitle": "API"
|
"groupTitle": "API"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get",
|
||||||
|
"url": "/api.php?q=node-info",
|
||||||
|
"title": "21. node-info",
|
||||||
|
"name": "node_info",
|
||||||
|
"group": "API",
|
||||||
|
"description": "<p>Returns details about the node.</p>",
|
||||||
|
"success": {
|
||||||
|
"fields": {
|
||||||
|
"Success 200": [
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "object",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data",
|
||||||
|
"description": "<p>A collection of data about the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.hostname",
|
||||||
|
"description": "<p>The hostname of the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.version",
|
||||||
|
"description": "<p>The current version of the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "string",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.dbversion",
|
||||||
|
"description": "<p>The database schema version for the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.accounts",
|
||||||
|
"description": "<p>The number of accounts known by the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.transactions",
|
||||||
|
"description": "<p>The number of transactions known by the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.mempool",
|
||||||
|
"description": "<p>The number of transactions in the mempool.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.masternodes",
|
||||||
|
"description": "<p>The number of masternodes known by the node.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.peers",
|
||||||
|
"description": "<p>The number of valid peers.</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"filename": "./api.php",
|
||||||
|
"groupTitle": "API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=randomNumber",
|
"url": "/api.php?q=randomNumber",
|
||||||
@@ -1073,6 +1197,51 @@
|
|||||||
"filename": "./api.php",
|
"filename": "./api.php",
|
||||||
"groupTitle": "API"
|
"groupTitle": "API"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "get",
|
||||||
|
"url": "/api.php?q=sanity",
|
||||||
|
"title": "20. sanity",
|
||||||
|
"name": "sanity",
|
||||||
|
"group": "API",
|
||||||
|
"description": "<p>Returns details about the node's sanity process.</p>",
|
||||||
|
"success": {
|
||||||
|
"fields": {
|
||||||
|
"Success 200": [
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "object",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data",
|
||||||
|
"description": "<p>A collection of data about the sanity process.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "boolean",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.sanity_running",
|
||||||
|
"description": "<p>Whether the sanity process is currently running.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "number",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.last_sanity",
|
||||||
|
"description": "<p>The timestamp for the last time the sanity process was run.</p>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": "Success 200",
|
||||||
|
"type": "boolean",
|
||||||
|
"optional": false,
|
||||||
|
"field": "data.sanity_sync",
|
||||||
|
"description": "<p>Whether the sanity process is currently synchronising.</p>"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": "0.0.0",
|
||||||
|
"filename": "./api.php",
|
||||||
|
"groupTitle": "API"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"type": "get",
|
"type": "get",
|
||||||
"url": "/api.php?q=send",
|
"url": "/api.php?q=send",
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ define({
|
|||||||
"apidoc": "0.3.0",
|
"apidoc": "0.3.0",
|
||||||
"generator": {
|
"generator": {
|
||||||
"name": "apidoc",
|
"name": "apidoc",
|
||||||
"time": "2018-08-05T21:17:14.214Z",
|
"time": "2018-11-05T10:13:13.657Z",
|
||||||
"url": "http://apidocjs.com",
|
"url": "http://apidocjs.com",
|
||||||
"version": "0.17.6"
|
"version": "0.17.6"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
"apidoc": "0.3.0",
|
"apidoc": "0.3.0",
|
||||||
"generator": {
|
"generator": {
|
||||||
"name": "apidoc",
|
"name": "apidoc",
|
||||||
"time": "2018-08-05T21:17:14.214Z",
|
"time": "2018-11-05T10:13:13.657Z",
|
||||||
"url": "http://apidocjs.com",
|
"url": "http://apidocjs.com",
|
||||||
"version": "0.17.6"
|
"version": "0.17.6"
|
||||||
}
|
}
|
||||||
|
|||||||
50
include/Blacklist.php
Normal file
50
include/Blacklist.php
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Arionum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Blacklist
|
||||||
|
*/
|
||||||
|
final class Blacklist
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The official list of blacklisted public keys
|
||||||
|
*/
|
||||||
|
public const PUBLIC_KEYS = [
|
||||||
|
// phpcs:disable Generic.Files.LineLength
|
||||||
|
'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCvVQcHHCNLfiP9LmzWhhpCHx39Bhc67P5HMQM9cctEFvcsUdgrkGqy18taz9ZMrAGtq7NhBYpQ4ZTHkKYiZDaSUqQ' => 'Faucet Abuser',
|
||||||
|
'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCxYDeQHk7Ke66UB2Un3UMmMoJ7RF5vDZXihdEXi8gk8ZBRAi35aFrER2ZLX1mgND7sLFXKETGTjRYjoHcuRNiJN1g' => 'Octaex Exchange',
|
||||||
|
// phpcs:enable
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The official list of blacklisted addresses
|
||||||
|
*/
|
||||||
|
public const ADDRESSES = [
|
||||||
|
// phpcs:disable Generic.Files.LineLength
|
||||||
|
'xuzyMbEGA1tmx1o7mcxSXf2nXuuV1GtKbA4sAqjcNq2gh3shuhwBT5nJHez9AynCaxpJwL6dpkavmZBA3JkrMkg' => 'Octaex Exchange',
|
||||||
|
// phpcs:enable
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a public key is blacklisted
|
||||||
|
*
|
||||||
|
* @param string $publicKey
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function checkPublicKey(string $publicKey): bool
|
||||||
|
{
|
||||||
|
return key_exists($publicKey, static::PUBLIC_KEYS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an address is blacklisted
|
||||||
|
*
|
||||||
|
* @param string $address
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function checkAddress(string $address): bool
|
||||||
|
{
|
||||||
|
return key_exists($address, static::ADDRESSES);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
include/Exception.php
Normal file
11
include/Exception.php
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Arionum\Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Exception
|
||||||
|
* A custom exception for Arionum error handling.
|
||||||
|
*/
|
||||||
|
class Exception extends \Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
81
include/InitialPeers.php
Normal file
81
include/InitialPeers.php
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Arionum\Node;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class InitialPeers
|
||||||
|
*/
|
||||||
|
final class InitialPeers
|
||||||
|
{
|
||||||
|
public const MINIMUM_PEERS_REQUIRED = 2;
|
||||||
|
public const PRELOAD_ERROR = 'Unable to retrieve peers from the preload list.';
|
||||||
|
public const PRELOAD_LIST = 'https://www.arionum.com/peers.txt';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
private $peerList = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InitialPeers constructor.
|
||||||
|
* @param array|null $peerList
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct(?array $peerList = [])
|
||||||
|
{
|
||||||
|
$this->peerList = $peerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a peer from the initial peer list.
|
||||||
|
* @return string
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function get(): string
|
||||||
|
{
|
||||||
|
if (!$this->peerList || count($this->peerList) < self::MINIMUM_PEERS_REQUIRED) {
|
||||||
|
$this->retrieveFromPreloadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->selectPeer();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all available initial peers.
|
||||||
|
* @return array
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public function getAll(): array
|
||||||
|
{
|
||||||
|
if (!$this->peerList || count($this->peerList) < self::MINIMUM_PEERS_REQUIRED) {
|
||||||
|
$this->retrieveFromPreloadList();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->peerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function selectPeer(): string
|
||||||
|
{
|
||||||
|
return $this->peerList[array_rand($this->peerList)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a peer from
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function retrieveFromPreloadList(): void
|
||||||
|
{
|
||||||
|
$peerList = file(self::PRELOAD_LIST, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
||||||
|
|
||||||
|
if (!$peerList || count($peerList) < self::MINIMUM_PEERS_REQUIRED) {
|
||||||
|
throw new Exception(self::PRELOAD_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->peerList = $peerList;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,8 +35,40 @@ class Account
|
|||||||
return 'RncXQuc7S7aWkvTUJSHEFvYoV3ntAf7bfxEHjSiZNBvQV37MzZtg44L7GAV7szZ3uV8qWqikBewa3piZMqzBqm';
|
return 'RncXQuc7S7aWkvTUJSHEFvYoV3ntAf7bfxEHjSiZNBvQV37MzZtg44L7GAV7szZ3uV8qWqikBewa3piZMqzBqm';
|
||||||
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCyjKMBY4ihhJ2G25EVezg7KnoCBVbhdvWfqzNA4LC5R7wgu3VNfJgvqkCq9sKKZcCoCpX6Qr9cN882MoXsfGTvZoj') {
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCyjKMBY4ihhJ2G25EVezg7KnoCBVbhdvWfqzNA4LC5R7wgu3VNfJgvqkCq9sKKZcCoCpX6Qr9cN882MoXsfGTvZoj') {
|
||||||
return 'Rq53oLzpCrb4BdJZ1jqQ2zsixV2ukxVdM4H9uvUhCGJCz1q2wagvuXV4hC6UVwK7HqAt1FenukzhVXgzyG1y32';
|
return 'Rq53oLzpCrb4BdJZ1jqQ2zsixV2ukxVdM4H9uvUhCGJCz1q2wagvuXV4hC6UVwK7HqAt1FenukzhVXgzyG1y32';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzZtEj6zAW8WVB6AbDLndbQZrnH2R5Nmpk1sLyHXzqyp4P5cyJAbnUpR5UdG8sBCCuZekWSBHgWNMaGS317vPsVuG'){
|
||||||
|
// mixed keys badly generated address
|
||||||
|
return '3CWXXqpzuda85MaPpgYRee8d7a44wzemqztfFfeZDyEysQ15cN6gZNsPT32MHwjrzbENDvkqKtADoCBgVVqXWP2g';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCwYhtqidHRVigBiQiun5csb9YnZzcvmSt7aCVS6nH2gYykLr9pQfJHP8bTtYTMkU1WLdmeTkNPGDujYWKjPSGU8XX'){
|
||||||
|
// broken wallet due to webwallet bug
|
||||||
|
return '4JstC5anTNMpY2zmUHt2LDmQXsMQvkh7d9qHBjBhRahAsWVTyyS9RPYMRdmcqdVPSDUQsXJfGyPFMn6y6R9M5QQ7';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCwoUzVYoaDZGausEDEg5JMtiRQvdmuuv1FKvCxUp6m8iMJhKbohtH75wXPBgi4wYPMSUw4himHeJ3qnDpAQnKSsJU'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return '4VLRngC3U24YdusKQ4rGfCX4DDfBUcNemH419wUS5xe2uUf3ku1CXq6RCfGoiZvDK61upmLfrb64YWubyh5eUG4Y';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCvgAVPik2t9yfM63rDCy13opmvejvMXadRb6qKjEoaiFkGCJHKBUSzggaEtgyDVkRk7ajREQjRrN6J4EcoXTzGM3p'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return 'SBWPS7Yu4X4ZQFY9n27bkBL5AnDRveUBbfbZWwhEN1tWZnTCEc8kvx7ddfoaqhjw7tw8rQULk2fEgSB1r2vWqKp';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCz1Adkpo6MRTogSUKLtEh5NKo1Y8sumnNKqhRW8w2bZtVfMT4sfbStg8ycqtmQNDztvUE39MVHnXmCDtpmv9KKdQN'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return 'reMoRxfiUxtoj7RD1aDH5yNfeuXEyTj2XiHaUBdVUhk8Wt5f4VLWrqge6J5yE9BGkVLFPqfS6ZYvj4ocWhbZhru';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCxXrhv7wkhX4R2YjyRNfssf15wTksz5Ev4FFGfCmhcUL7kt5aXRvh6xknQf5HHzDo4GsG523wBYcFhiAkmBL1kkUo'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return '3goaif939N4xy5ThT7iq2GhBgwjrS4buhhTtTQkXrzarKcsYvyg5PU8KVgzrSfgFfhnZGNx9WseaR2JSUpYn1Vch';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzhTJ5G37ijQcgdzUsMMVyAPFaxLCyssQjqYF1g1Zsr3XkzYux3Dt75y3DRmXmx6wiNTf7uKxAGFaQA7qao7TXp9j'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return 'LtjGjTTurwLNZLbexAbusCRS5SNYhFydMuFdPTaYFRD3WoL2q67tidsrd7qnX8czmTBhrDyrdheP5gCwCbAHBBd';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCwrgAsdSZtv9e4Ldw2mzg7HwQMHzG1FFVzoRtENwDRZxhRTwSGYU4oUXVLzNWNqpRZ6iEZXenxUANScwr7yDET7xA'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return 'aSpfMMbxA8U1rMqBgYoQtXhUyAKyhBJHY17CEW4V3ttgRsvpuZ1Dg3xYc1rcMeKnP2gT2sxnn7vHpmLAVVPQv7w';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCzPi4ZmDK5E7vNVz14AiJmvcT9UbxXDDWzNVYt973Sqgt6p6BQtuqkJ3X3UM92mbjxVLg3xzmhZricuUSx5J811nW'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return '98MsWpiv3fcutf4Mm94wYKZeeS556EAvMWEBLc12y5nf5QzNtD6hDfCuWcJMUr9Q9qmbj8kS326EGuiiTW7YJDo';
|
||||||
|
} elseif ($hash == 'PZ8Tyr4Nx8MHsRAGMpZmZ6TWY63dXWSCz9iKvAxdReMiDYmBWJb3GnjeTnNLwE8y7fuyBwFDbRLpECwnscbXSLGXMmvPMbMMRYSnnc7aTyLJBzw7tqxGNw4K'){
|
||||||
|
// stolen coins hf recovery
|
||||||
|
return '2xQGMH8qQuaTeKSYya5wYPWA9dgqiKBBDSeDWu1aUuBhKi8LnsukknqcUDRdzS7VVeC7aezK6Azhkx6L7H24pUjo';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// hashes 9 times in sha512 (binary) and encodes in base58
|
// hashes 9 times in sha512 (binary) and encodes in base58
|
||||||
for ($i = 0; $i < 9;
|
for ($i = 0; $i < 9;
|
||||||
$i++) {
|
$i++) {
|
||||||
@@ -103,7 +135,7 @@ class Account
|
|||||||
if (strlen($id)<4||strlen($id)>25) {
|
if (strlen($id)<4||strlen($id)>25) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if($orig!=$id){
|
if ($orig!=$id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,12 +147,16 @@ class Account
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check if an account already has an alias
|
//check if an account already has an alias
|
||||||
public function has_alias($public_key){
|
public function has_alias($public_key)
|
||||||
|
{
|
||||||
global $db;
|
global $db;
|
||||||
$public_key=san($public_key);
|
$public_key=san($public_key);
|
||||||
$res=$db->single("SELECT COUNT(1) FROM accounts WHERE public_key=:public_key AND alias IS NOT NULL",[":public_key"=>$public_key]);
|
$res=$db->single("SELECT COUNT(1) FROM accounts WHERE public_key=:public_key AND alias IS NOT NULL", [":public_key"=>$public_key]);
|
||||||
if($res!=0) return true;
|
if ($res!=0) {
|
||||||
else return false;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//check alias validity
|
//check alias validity
|
||||||
@@ -137,25 +173,27 @@ class Account
|
|||||||
if (strlen($id)<4||strlen($id)>25) {
|
if (strlen($id)<4||strlen($id)>25) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if($orig!=$id){
|
if ($orig!=$id) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return $db->single("SELECT COUNT(1) FROM accounts WHERE alias=:alias", [":alias"=>$id]);
|
return $db->single("SELECT COUNT(1) FROM accounts WHERE alias=:alias", [":alias"=>$id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns the account of an alias
|
//returns the account of an alias
|
||||||
public function alias2account($alias){
|
public function alias2account($alias)
|
||||||
|
{
|
||||||
global $db;
|
global $db;
|
||||||
$alias=strtoupper($alias);
|
$alias=strtoupper($alias);
|
||||||
$res=$db->single("SELECT id FROM accounts WHERE alias=:alias LIMIT 1",[":alias"=>$alias]);
|
$res=$db->single("SELECT id FROM accounts WHERE alias=:alias LIMIT 1", [":alias"=>$alias]);
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns the alias of an account
|
//returns the alias of an account
|
||||||
public function account2alias($id){
|
public function account2alias($id)
|
||||||
|
{
|
||||||
global $db;
|
global $db;
|
||||||
$id=san($id);
|
$id=san($id);
|
||||||
$res=$db->single("SELECT alias FROM accounts WHERE id=:id LIMIT 1",[":id"=>$id]);
|
$res=$db->single("SELECT alias FROM accounts WHERE id=:id LIMIT 1", [":id"=>$id]);
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
// check the validity of an address. At the moment, it checks only the characters to be base58 and the length to be >=70 and <=128.
|
// check the validity of an address. At the moment, it checks only the characters to be base58 and the length to be >=70 and <=128.
|
||||||
@@ -212,13 +250,14 @@ class Account
|
|||||||
$block = new Block();
|
$block = new Block();
|
||||||
$current = $block->current();
|
$current = $block->current();
|
||||||
$public_key = $this->public_key($id);
|
$public_key = $this->public_key($id);
|
||||||
|
$alias = $this->account2alias($id);
|
||||||
$limit = intval($limit);
|
$limit = intval($limit);
|
||||||
if ($limit > 100 || $limit < 1) {
|
if ($limit > 100 || $limit < 1) {
|
||||||
$limit = 100;
|
$limit = 100;
|
||||||
}
|
}
|
||||||
$res = $db->run(
|
$res = $db->run(
|
||||||
"SELECT * FROM transactions WHERE dst=:dst or public_key=:src ORDER by height DESC LIMIT :limit",
|
"SELECT * FROM transactions WHERE dst=:dst or public_key=:src or dst=:alias ORDER by height DESC LIMIT :limit",
|
||||||
[":src" => $public_key, ":dst" => $id, ":limit" => $limit]
|
[":src" => $public_key, ":dst" => $id, ":limit" => $limit, ":alias"=>$alias]
|
||||||
);
|
);
|
||||||
|
|
||||||
$transactions = [];
|
$transactions = [];
|
||||||
@@ -299,11 +338,13 @@ class Account
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_masternode($public_key){
|
public function get_masternode($public_key)
|
||||||
|
{
|
||||||
global $db;
|
global $db;
|
||||||
$res = $db->row("SELECT * FROM masternode WHERE public_key=:public_key", [":public_key" => $public_key]);
|
$res = $db->row("SELECT * FROM masternode WHERE public_key=:public_key", [":public_key" => $public_key]);
|
||||||
if(empty($res['public_key'])) return false;
|
if (empty($res['public_key'])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class Block
|
|||||||
|
|
||||||
// create the block data and check it against the signature
|
// create the block data and check it against the signature
|
||||||
$info = "{$generator}-{$height}-{$date}-{$nonce}-{$json}-{$difficulty}-{$argon}";
|
$info = "{$generator}-{$height}-{$date}-{$nonce}-{$json}-{$difficulty}-{$argon}";
|
||||||
_log($info,3);
|
// _log($info,3);
|
||||||
if (!$bootstrapping) {
|
if (!$bootstrapping) {
|
||||||
if (!$acc->check_signature($info, $signature, $public_key)) {
|
if (!$acc->check_signature($info, $signature, $public_key)) {
|
||||||
_log("Block signature check failed");
|
_log("Block signature check failed");
|
||||||
@@ -37,12 +37,32 @@ class Block
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// lock table to avoid race conditions on blocks
|
// lock table to avoid race conditions on blocks
|
||||||
$db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE");
|
$db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE, masternode WRITE, peers write, config WRITE");
|
||||||
|
|
||||||
$reward = $this->reward($height, $data);
|
$reward = $this->reward($height, $data);
|
||||||
|
|
||||||
$msg = '';
|
$msg = '';
|
||||||
|
|
||||||
|
if ($height>=80458) {
|
||||||
|
//reward the masternode
|
||||||
|
|
||||||
|
$mn_winner=$db->single(
|
||||||
|
"SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 1",
|
||||||
|
[":current"=>$height, ":start"=>$height-360]
|
||||||
|
);
|
||||||
|
_log("MN Winner: $mn_winner", 2);
|
||||||
|
if ($mn_winner!==false) {
|
||||||
|
$mn_reward=round(0.33*$reward, 8);
|
||||||
|
$reward=round($reward-$mn_reward, 8);
|
||||||
|
$reward=number_format($reward, 8, ".", "");
|
||||||
|
$mn_reward=number_format($mn_reward, 8, ".", "");
|
||||||
|
_log("MN Reward: $mn_reward", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// the reward transaction
|
// the reward transaction
|
||||||
$transaction = [
|
$transaction = [
|
||||||
"src" => $generator,
|
"src" => $generator,
|
||||||
@@ -68,6 +88,8 @@ class Block
|
|||||||
// insert the block into the db
|
// insert the block into the db
|
||||||
$db->beginTransaction();
|
$db->beginTransaction();
|
||||||
$total = count($data);
|
$total = count($data);
|
||||||
|
|
||||||
|
|
||||||
$bind = [
|
$bind = [
|
||||||
":id" => $hash,
|
":id" => $hash,
|
||||||
":generator" => $generator,
|
":generator" => $generator,
|
||||||
@@ -92,12 +114,57 @@ class Block
|
|||||||
}
|
}
|
||||||
|
|
||||||
// insert the reward transaction in the db
|
// insert the reward transaction in the db
|
||||||
$trx->add($hash, $height, $transaction);
|
$res=$trx->add($hash, $height, $transaction);
|
||||||
|
if ($res == false) {
|
||||||
|
// rollback and exit if it fails
|
||||||
|
_log("Reward DB insert failed");
|
||||||
|
$db->rollback();
|
||||||
|
$db->exec("UNLOCK TABLES");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($mn_winner!==false&&$height>=80458&&$mn_reward>0) {
|
||||||
|
$db->run("UPDATE accounts SET balance=balance+:bal WHERE public_key=:pub", [":pub"=>$mn_winner, ":bal"=>$mn_reward]);
|
||||||
|
$bind = [
|
||||||
|
":id" => hex2coin(hash("sha512", "mn".$hash.$height.$mn_winner)),
|
||||||
|
":public_key" => $public_key,
|
||||||
|
":height" => $height,
|
||||||
|
":block" => $hash,
|
||||||
|
":dst" => $acc->get_address($mn_winner),
|
||||||
|
":val" => $mn_reward,
|
||||||
|
":fee" => 0,
|
||||||
|
":signature" => $reward_signature,
|
||||||
|
":version" => 0,
|
||||||
|
":date" => $date,
|
||||||
|
":message" => 'masternode',
|
||||||
|
];
|
||||||
|
$res = $db->run(
|
||||||
|
"INSERT into transactions SET id=:id, public_key=:public_key, block=:block, height=:height, dst=:dst, val=:val, fee=:fee, signature=:signature, version=:version, message=:message, `date`=:date",
|
||||||
|
$bind
|
||||||
|
);
|
||||||
|
if ($res != 1) {
|
||||||
|
// rollback and exit if it fails
|
||||||
|
_log("Masternode reward DB insert failed");
|
||||||
|
$db->rollback();
|
||||||
|
$db->exec("UNLOCK TABLES");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$res=$this->reset_fails_masternodes($mn_winner, $height, $hash);
|
||||||
|
if (!$res) {
|
||||||
|
|
||||||
|
// rollback and exit if it fails
|
||||||
|
_log("Masternode log DB insert failed");
|
||||||
|
$db->rollback();
|
||||||
|
$db->exec("UNLOCK TABLES");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->do_hard_forks($height, $hash);
|
||||||
|
}
|
||||||
|
|
||||||
// parse the block's transactions and insert them to db
|
// parse the block's transactions and insert them to db
|
||||||
$res = $this->parse_block($hash, $height, $data, false, $bootstrapping);
|
$res = $this->parse_block($hash, $height, $data, false, $bootstrapping);
|
||||||
|
|
||||||
if (($height-1)%3==2 && $height>=80000) {
|
if (($height-1)%3==2 && $height>=80000&&$height<80458) {
|
||||||
$this->blacklist_masternodes();
|
$this->blacklist_masternodes();
|
||||||
$this->reset_fails_masternodes($public_key, $height, $hash);
|
$this->reset_fails_masternodes($public_key, $height, $hash);
|
||||||
}
|
}
|
||||||
@@ -112,16 +179,91 @@ class Block
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function do_hard_forks($height, $block)
|
||||||
|
{
|
||||||
|
global $db;
|
||||||
|
if ($height==126215) {
|
||||||
|
// compromised masternodes are being removed
|
||||||
|
$mns=['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',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($mns as $mn) {
|
||||||
|
$db->run("DELETE FROM masternode WHERE public_key=:p", [":p"=>$mn]);
|
||||||
|
}
|
||||||
|
// their locked coins are added to dev's safewallet
|
||||||
|
$id=hex2coin(hash("sha512", "hf".$block.$height.'compromised-masternodes'));
|
||||||
|
$res=$db->run(
|
||||||
|
"INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=4700000, fee=0, signature=:sig, version=0, message=:msg, date=:date, public_key=:public_key",
|
||||||
|
[":id"=>$id, ":block"=>$block, ":height"=>$height, ":dst"=>'4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP', ":sig"=>$id, ":msg"=>'compromised-masternodes-hf', ":date"=>time(), ":public_key"=>'4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP']
|
||||||
|
);
|
||||||
|
$db->run("UPDATE accounts SET balance=balance+4700000 where id='4kWXV4HMuogUcjZBEzmmQdtc1dHzta6VykhCV1HWyEXK7kRWEMJLNoMWbuDwFMTfBrq5a9VthkZfmkMkamTfwRBP' LIMIT 1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// resets the number of fails when winning a block and marks it with a transaction
|
// resets the number of fails when winning a block and marks it with a transaction
|
||||||
|
|
||||||
public function reset_fails_masternodes($public_key, $height, $hash)
|
public function reset_fails_masternodes($public_key, $height, $hash)
|
||||||
{
|
{
|
||||||
global $db;
|
global $db;
|
||||||
$res=$this->masternode_log($public_key, $height, $hash);
|
$res=$this->masternode_log($public_key, $height, $hash);
|
||||||
|
if ($res===5) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if ($res) {
|
if ($res) {
|
||||||
$db->run("UPDATE masternode SET last_won=:last_won,fails=0 WHERE public_key=:public_key", [":public_key"=>$public_key, ":last_won"=>$height]);
|
$rez=$db->run("UPDATE masternode SET last_won=:last_won,fails=0 WHERE public_key=:public_key", [":public_key"=>$public_key, ":last_won"=>$height]);
|
||||||
|
if ($rez!=1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//logs the current masternode status
|
//logs the current masternode status
|
||||||
@@ -138,12 +280,15 @@ class Block
|
|||||||
$id = hex2coin(hash("sha512", "resetfails-$hash-$height-$public_key"));
|
$id = hex2coin(hash("sha512", "resetfails-$hash-$height-$public_key"));
|
||||||
$msg="$mn[blacklist],$mn[last_won],$mn[fails]";
|
$msg="$mn[blacklist],$mn[last_won],$mn[fails]";
|
||||||
|
|
||||||
$db->run(
|
$res=$db->run(
|
||||||
|
|
||||||
"INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=0, fee=0, signature=:sig, version=111, message=:msg, date=:date, public_key=:public_key",
|
"INSERT into transactions SET id=:id, block=:block, height=:height, dst=:dst, val=0, fee=0, signature=:sig, version=111, message=:msg, date=:date, public_key=:public_key",
|
||||||
[":id"=>$id, ":block"=>$hash, ":height"=>$height, ":dst"=>$hash, ":sig"=>$hash, ":msg"=>$msg, ":date"=>time(), ":public_key"=>$public_key]
|
[":id"=>$id, ":block"=>$hash, ":height"=>$height, ":dst"=>$hash, ":sig"=>$hash, ":msg"=>$msg, ":date"=>time(), ":public_key"=>$public_key]
|
||||||
|
|
||||||
);
|
);
|
||||||
|
if ($res!=1) {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +328,8 @@ class Block
|
|||||||
|
|
||||||
$height = $current['height'];
|
$height = $current['height'];
|
||||||
|
|
||||||
if ($height == 10801) {
|
if ($height == 10801||($height>=80456&&$height<80460)) {
|
||||||
return 5555555555; //hard fork 10900 resistance, force new difficulty
|
return "5555555555"; //hard fork 10900 resistance, force new difficulty
|
||||||
}
|
}
|
||||||
|
|
||||||
// last 20 blocks used to check the block times
|
// last 20 blocks used to check the block times
|
||||||
@@ -201,7 +346,7 @@ class Block
|
|||||||
// before mnn hf
|
// before mnn hf
|
||||||
if ($height<80000) {
|
if ($height<80000) {
|
||||||
// elapsed time between the last 20 blocks
|
// elapsed time between the last 20 blocks
|
||||||
$first = $db->row("SELECT `date` FROM blocks ORDER by height DESC LIMIT $limit,1");
|
$first = $db->row("SELECT `date` FROM blocks ORDER by height DESC LIMIT :limit,1", [":limit"=>$limit]);
|
||||||
$time = $current['date'] - $first['date'];
|
$time = $current['date'] - $first['date'];
|
||||||
|
|
||||||
// avg block time
|
// avg block time
|
||||||
@@ -219,6 +364,32 @@ class Block
|
|||||||
// keep current difficulty
|
// keep current difficulty
|
||||||
$dif = $current['difficulty'];
|
$dif = $current['difficulty'];
|
||||||
}
|
}
|
||||||
|
} elseif ($height>=80458) {
|
||||||
|
$type=$height%2;
|
||||||
|
$current=$db->row("SELECT difficulty from blocks WHERE height<=:h ORDER by height DESC LIMIT 1,1", [":h"=>$height]);
|
||||||
|
$blks=0;
|
||||||
|
$total_time=0;
|
||||||
|
$blk = $db->run("SELECT `date`, height FROM blocks WHERE height<=:h ORDER by height DESC LIMIT 20", [":h"=>$height]);
|
||||||
|
for ($i=0;$i<19;$i++) {
|
||||||
|
$ctype=$blk[$i+1]['height']%2;
|
||||||
|
$time=$blk[$i]['date']-$blk[$i+1]['date'];
|
||||||
|
if ($type!=$ctype) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$blks++;
|
||||||
|
$total_time+=$time;
|
||||||
|
}
|
||||||
|
$result=ceil($total_time/$blks);
|
||||||
|
_log("Block time: $result", 3);
|
||||||
|
if ($result > 260) {
|
||||||
|
$dif = bcmul($current['difficulty'], 1.05);
|
||||||
|
} elseif ($result < 220) {
|
||||||
|
// if lower, decrease by 5%
|
||||||
|
$dif = bcmul($current['difficulty'], 0.95);
|
||||||
|
} else {
|
||||||
|
// keep current difficulty
|
||||||
|
$dif = $current['difficulty'];
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// hardfork 80000, fix difficulty targetting
|
// hardfork 80000, fix difficulty targetting
|
||||||
|
|
||||||
@@ -227,7 +398,7 @@ class Block
|
|||||||
$type=$height%3;
|
$type=$height%3;
|
||||||
// for mn, we use gpu diff
|
// for mn, we use gpu diff
|
||||||
if ($type == 2) {
|
if ($type == 2) {
|
||||||
return $current['difficulty'];
|
return $current['difficulty'];
|
||||||
}
|
}
|
||||||
|
|
||||||
$blks=0;
|
$blks=0;
|
||||||
@@ -324,8 +495,8 @@ class Block
|
|||||||
}
|
}
|
||||||
$acc = new Account();
|
$acc = new Account();
|
||||||
|
|
||||||
if($data['date']>time()+30){
|
if ($data['date']>time()+30) {
|
||||||
_log("Future block - $data[date] $data[public_key]",2);
|
_log("Future block - $data[date] $data[public_key]", 2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,6 +556,24 @@ class Block
|
|||||||
|
|
||||||
// reward transaction and signature
|
// reward transaction and signature
|
||||||
$reward = $this->reward($height, $data);
|
$reward = $this->reward($height, $data);
|
||||||
|
|
||||||
|
if ($height>=80458) {
|
||||||
|
//reward the masternode
|
||||||
|
global $db;
|
||||||
|
$mn_winner=$db->single(
|
||||||
|
"SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 1",
|
||||||
|
[":current"=>$height, ":start"=>$height-360]
|
||||||
|
);
|
||||||
|
_log("MN Winner: $mn_winner", 2);
|
||||||
|
if ($mn_winner!==false) {
|
||||||
|
$mn_reward=round(0.33*$reward, 8);
|
||||||
|
$reward=round($reward-$mn_reward, 8);
|
||||||
|
$reward=number_format($reward, 8, ".", "");
|
||||||
|
$mn_reward=number_format($mn_reward, 8, ".", "");
|
||||||
|
_log("MN Reward: $mn_reward", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$msg = '';
|
$msg = '';
|
||||||
$transaction = [
|
$transaction = [
|
||||||
"src" => $generator,
|
"src" => $generator,
|
||||||
@@ -430,21 +619,36 @@ class Block
|
|||||||
$last=$this->get($current['height']-1);
|
$last=$this->get($current['height']-1);
|
||||||
$total_time=$current['date']-$last['date'];
|
$total_time=$current['date']-$last['date'];
|
||||||
_log("blacklist total time $total_time");
|
_log("blacklist total time $total_time");
|
||||||
if ($total_time<=600) {
|
if ($total_time<=600&&$current['height']<80500) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$tem=floor($total_time/600);
|
if ($current['height']>=80500&&$total_time<360) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($current['height']>=80500) {
|
||||||
|
$total_time-=360;
|
||||||
|
$tem=floor($total_time/120)+1;
|
||||||
|
if ($tem>5) {
|
||||||
|
$tem=5;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$tem=floor($total_time/600);
|
||||||
|
}
|
||||||
_log("We have masternodes to blacklist - $tem", 2);
|
_log("We have masternodes to blacklist - $tem", 2);
|
||||||
$ban=$db->run(
|
$ban=$db->run(
|
||||||
"SELECT public_key, blacklist, fails, last_won FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 0,$tem",
|
"SELECT public_key, blacklist, fails, last_won FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 0,:limit",
|
||||||
[":current"=>$last['height'], ":start"=>$last['height']-360]
|
[":current"=>$last['height'], ":start"=>$last['height']-360, ":limit"=>$tem]
|
||||||
);
|
);
|
||||||
_log(json_encode($ban));
|
_log(json_encode($ban));
|
||||||
$i=0;
|
$i=0;
|
||||||
foreach ($ban as $b) {
|
foreach ($ban as $b) {
|
||||||
$this->masternode_log($b['public_key'], $current['height'], $current['id']);
|
$this->masternode_log($b['public_key'], $current['height'], $current['id']);
|
||||||
_log("Blacklisting masternode - $i $b[public_key]", 2);
|
_log("Blacklisting masternode - $i $b[public_key]", 2);
|
||||||
$db->run("UPDATE masternode SET fails=fails+1, blacklist=:blacklist WHERE public_key=:public_key", [":public_key"=>$b['public_key'], ":blacklist"=> $current['height']+(($b['fails']+1)*10)]);
|
$btime=10;
|
||||||
|
if ($current['height']>83000) {
|
||||||
|
$btime=360;
|
||||||
|
}
|
||||||
|
$db->run("UPDATE masternode SET fails=fails+1, blacklist=:blacklist WHERE public_key=:public_key", [":public_key"=>$b['public_key'], ":blacklist"=> $current['height']+(($b['fails']+1)*$btime)]);
|
||||||
$i++;
|
$i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -455,7 +659,7 @@ class Block
|
|||||||
global $_config;
|
global $_config;
|
||||||
|
|
||||||
// invalid future blocks
|
// invalid future blocks
|
||||||
if($time>time()+30){
|
if ($time>time()+30) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,6 +694,16 @@ class Block
|
|||||||
_log("Block below 10800, using 16MB argon", 2);
|
_log("Block below 10800, using 16MB argon", 2);
|
||||||
$argon = '$argon2i$v=19$m=16384,t=4,p=4'.$argon;
|
$argon = '$argon2i$v=19$m=16384,t=4,p=4'.$argon;
|
||||||
}
|
}
|
||||||
|
} elseif ($current_height>=80458) {
|
||||||
|
if ($current_height%2==0) {
|
||||||
|
// cpu mining
|
||||||
|
_log("CPU Mining - $current_height", 2);
|
||||||
|
$argon = '$argon2i$v=19$m=524288,t=1,p=1'.$argon;
|
||||||
|
} else {
|
||||||
|
// gpu mining
|
||||||
|
_log("GPU Mining - $current_height", 2);
|
||||||
|
$argon = '$argon2i$v=19$m=16384,t=4,p=4'.$argon;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
_log("Block > 80000 - $current_height", 2);
|
_log("Block > 80000 - $current_height", 2);
|
||||||
if ($current_height%3==0) {
|
if ($current_height%3==0) {
|
||||||
@@ -535,19 +749,24 @@ class Block
|
|||||||
}
|
}
|
||||||
// if 10 mins have passed, try to give the block to the next masternode and do this every 10mins
|
// if 10 mins have passed, try to give the block to the next masternode and do this every 10mins
|
||||||
_log("Last block time: $last_time, difference: ".($time-$last_time), 3);
|
_log("Last block time: $last_time, difference: ".($time-$last_time), 3);
|
||||||
if ($time-$last_time>600) {
|
if (($time-$last_time>600&&$current_height<80500)||($time-$last_time>360&&$current_height>=80500)) {
|
||||||
_log("Current public_key $public_key", 3);
|
_log("Current public_key $public_key", 3);
|
||||||
$tem=floor(($time-$last_time)/600);
|
if ($current_height>=80500) {
|
||||||
|
$total_time=$time-$last_time;
|
||||||
|
$total_time-=360;
|
||||||
|
$tem=floor($total_time/120)+1;
|
||||||
|
} else {
|
||||||
|
$tem=floor(($time-$last_time)/600);
|
||||||
|
}
|
||||||
$winner=$db->single(
|
$winner=$db->single(
|
||||||
"SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT $tem,1",
|
"SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT :tem,1",
|
||||||
[":current"=>$current_height, ":start"=>$current_height-360]
|
[":current"=>$current_height, ":start"=>$current_height-360, ":tem"=>$tem]
|
||||||
);
|
);
|
||||||
_log("Moving to the next masternode - $tem - $winner", 1);
|
_log("Moving to the next masternode - $tem - $winner", 1);
|
||||||
// if all masternodes are dead, give the block to gpu
|
// if all masternodes are dead, give the block to gpu
|
||||||
if ($winner===false) {
|
if ($winner===false||($tem>=5&&$current_height>=80500)) {
|
||||||
_log("All masternodes failed, giving the block to gpu", 1);
|
_log("All masternodes failed, giving the block to gpu", 1);
|
||||||
$argon = '$argon2i$v=19$m=16384,t=1,p=1'.$argon;
|
$argon = '$argon2i$v=19$m=16384,t=4,p=4'.$argon;
|
||||||
} elseif ($winner==$public_key) {
|
} elseif ($winner==$public_key) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -612,6 +831,7 @@ class Block
|
|||||||
global $db;
|
global $db;
|
||||||
// data must be array
|
// data must be array
|
||||||
if ($data === false) {
|
if ($data === false) {
|
||||||
|
_log("Block data is false", 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$acc = new Account();
|
$acc = new Account();
|
||||||
@@ -624,6 +844,7 @@ class Block
|
|||||||
// check if the number of transactions is not bigger than current block size
|
// check if the number of transactions is not bigger than current block size
|
||||||
$max = $this->max_transactions();
|
$max = $this->max_transactions();
|
||||||
if (count($data) > $max) {
|
if (count($data) > $max) {
|
||||||
|
_log("Too many transactions in block", 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -638,6 +859,7 @@ class Block
|
|||||||
if (!$bootstrapping) {
|
if (!$bootstrapping) {
|
||||||
//validate the transaction
|
//validate the transaction
|
||||||
if (!$trx->check($x, $height)) {
|
if (!$trx->check($x, $height)) {
|
||||||
|
_log("Transaction check failed - $x[id]", 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($x['version']>=100&&$x['version']<110) {
|
if ($x['version']>=100&&$x['version']<110) {
|
||||||
@@ -650,6 +872,7 @@ class Block
|
|||||||
|
|
||||||
// check if the transaction is already on the blockchain
|
// check if the transaction is already on the blockchain
|
||||||
if ($db->single("SELECT COUNT(1) FROM transactions WHERE id=:id", [":id" => $x['id']]) > 0) {
|
if ($db->single("SELECT COUNT(1) FROM transactions WHERE id=:id", [":id" => $x['id']]) > 0) {
|
||||||
|
_log("Transaction already on the blockchain - $x[id]", 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -668,6 +891,7 @@ class Block
|
|||||||
[":id" => $id, ":balance" => $bal]
|
[":id" => $id, ":balance" => $bal]
|
||||||
);
|
);
|
||||||
if ($res == 0) {
|
if ($res == 0) {
|
||||||
|
_log("Not enough balance for transaction - $id", 3);
|
||||||
return false; // not enough balance for the transactions
|
return false; // not enough balance for the transactions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -745,12 +969,14 @@ class Block
|
|||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
$res = $trx->reverse($x['id']);
|
$res = $trx->reverse($x['id']);
|
||||||
if ($res === false) {
|
if ($res === false) {
|
||||||
|
_log("A transaction could not be reversed. Delete block failed.");
|
||||||
$db->rollback();
|
$db->rollback();
|
||||||
$db->exec("UNLOCK TABLES");
|
$db->exec("UNLOCK TABLES");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$res = $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['id']]);
|
$res = $db->run("DELETE FROM blocks WHERE id=:id", [":id" => $x['id']]);
|
||||||
if ($res != 1) {
|
if ($res != 1) {
|
||||||
|
_log("Delete block failed.");
|
||||||
$db->rollback();
|
$db->rollback();
|
||||||
$db->exec("UNLOCK TABLES");
|
$db->exec("UNLOCK TABLES");
|
||||||
return false;
|
return false;
|
||||||
@@ -863,7 +1089,7 @@ class Block
|
|||||||
|
|
||||||
// the reward transaction always has version 0
|
// the reward transaction always has version 0
|
||||||
$gen = $db->row(
|
$gen = $db->row(
|
||||||
"SELECT public_key, signature FROM transactions WHERE version=0 AND block=:block",
|
"SELECT public_key, signature FROM transactions WHERE version=0 AND block=:block AND message=''",
|
||||||
[":block" => $block['id']]
|
[":block" => $block['id']]
|
||||||
);
|
);
|
||||||
$block['public_key'] = $gen['public_key'];
|
$block['public_key'] = $gen['public_key'];
|
||||||
|
|||||||
156
include/config-sample.inc.php
Executable file
156
include/config-sample.inc.php
Executable file
@@ -0,0 +1,156 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Database Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The database DSN
|
||||||
|
$_config['db_connect'] = 'mysql:host=localhost;dbname=ENTER-DB-NAME';
|
||||||
|
|
||||||
|
// The database username
|
||||||
|
$_config['db_user'] = 'ENTER-DB-USER';
|
||||||
|
|
||||||
|
// The database password
|
||||||
|
$_config['db_pass'] = 'ENTER-DB-PASS';
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| General Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Maximum number of connected peers
|
||||||
|
$_config['max_peers'] = 30;
|
||||||
|
|
||||||
|
// Enable testnet mode for development
|
||||||
|
$_config['testnet'] = false;
|
||||||
|
|
||||||
|
// To avoid any problems if other clones are made
|
||||||
|
$_config['coin'] = 'arionum';
|
||||||
|
|
||||||
|
// Allow others to connect to the node api (if set to false, only the below 'allowed_hosts' are allowed)
|
||||||
|
$_config['public_api'] = true;
|
||||||
|
|
||||||
|
// Hosts that are allowed to mine on this node
|
||||||
|
$_config['allowed_hosts'] = [
|
||||||
|
'127.0.0.1',
|
||||||
|
];
|
||||||
|
|
||||||
|
// Disable transactions and block repropagation
|
||||||
|
$_config['disable_repropagation'] = false;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Peer Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The number of peers to send each new transaction to
|
||||||
|
$_config['transaction_propagation_peers'] = 5;
|
||||||
|
|
||||||
|
// How many new peers to check from each peer
|
||||||
|
$_config['max_test_peers'] = 5;
|
||||||
|
|
||||||
|
// The initial peers to sync from in sanity
|
||||||
|
$_config['initial_peer_list'] = [
|
||||||
|
'http://peer1.arionum.com',
|
||||||
|
'http://peer2.arionum.com',
|
||||||
|
'http://peer3.arionum.com',
|
||||||
|
'http://peer4.arionum.com',
|
||||||
|
'http://peer5.arionum.com',
|
||||||
|
'http://peer6.arionum.com',
|
||||||
|
'http://peer7.arionum.com',
|
||||||
|
'http://peer8.arionum.com',
|
||||||
|
'http://peer9.arionum.com',
|
||||||
|
'http://peer10.arionum.com',
|
||||||
|
'http://peer11.arionum.com',
|
||||||
|
'http://peer12.arionum.com',
|
||||||
|
'http://peer13.arionum.com',
|
||||||
|
'http://peer14.arionum.com',
|
||||||
|
'http://peer15.arionum.com',
|
||||||
|
'http://peer16.arionum.com',
|
||||||
|
'http://peer17.arionum.com',
|
||||||
|
'http://peer18.arionum.com',
|
||||||
|
'http://peer19.arionum.com',
|
||||||
|
'http://peer20.arionum.com',
|
||||||
|
'http://peer21.arionum.com',
|
||||||
|
'http://peer22.arionum.com',
|
||||||
|
'http://peer23.arionum.com',
|
||||||
|
'http://peer24.arionum.com',
|
||||||
|
'http://peer25.arionum.com',
|
||||||
|
'http://peer26.arionum.com',
|
||||||
|
'http://peer27.arionum.com',
|
||||||
|
];
|
||||||
|
|
||||||
|
// does not peer with any of the peers. Uses the seed peers and syncs only from those peers. Requires a cronjob on sanity.php
|
||||||
|
$_config['passive_peering'] = false;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Mempool Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The maximum transactions to accept from a single peer
|
||||||
|
$_config['peer_max_mempool'] = 100;
|
||||||
|
|
||||||
|
// The maximum number of mempool transactions to be rebroadcasted
|
||||||
|
$_config['max_mempool_rebroadcast'] = 5000;
|
||||||
|
|
||||||
|
// The number of blocks between rebroadcasting transactions
|
||||||
|
$_config['sanity_rebroadcast_height'] = 30;
|
||||||
|
|
||||||
|
// Block accepting transfers from addresses blacklisted by the Arionum devs
|
||||||
|
$_config['use_official_blacklist'] = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Sanity Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Recheck the last blocks on sanity
|
||||||
|
$_config['sanity_recheck_blocks'] = 10;
|
||||||
|
|
||||||
|
// The interval to run the sanity in seconds
|
||||||
|
$_config['sanity_interval'] = 900;
|
||||||
|
|
||||||
|
// Enable setting a new hostname (should be used only if you want to change the hostname)
|
||||||
|
$_config['allow_hostname_change'] = false;
|
||||||
|
|
||||||
|
// Rebroadcast local transactions when running sanity
|
||||||
|
$_config['sanity_rebroadcast_locals'] = true;
|
||||||
|
|
||||||
|
// Get more peers?
|
||||||
|
$_config['get_more_peers'] = true;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Logging Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Enable log output to the specified file
|
||||||
|
$_config['enable_logging'] = false;
|
||||||
|
|
||||||
|
// The specified file to write to (this should not be publicly visible)
|
||||||
|
$_config['log_file'] = '/var/log/aro.log';
|
||||||
|
|
||||||
|
// Log verbosity (default 0, maximum 3)
|
||||||
|
$_config['log_verbosity'] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Masternode Configuration
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Enable this node as a masternode
|
||||||
|
$_config['masternode'] = false;
|
||||||
|
|
||||||
|
// The public key for the masternode
|
||||||
|
$_config['masternode_public_key'] = '';
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
<?php
|
|
||||||
// Database connection
|
|
||||||
$_config['db_connect']="mysql:host=localhost;dbname=ENTER-DB-NAME";
|
|
||||||
$_config['db_user']="ENTER-DB-USER";
|
|
||||||
$_config['db_pass']="ENTER-DB-PASS";
|
|
||||||
|
|
||||||
// Maximum number of connected peers
|
|
||||||
$_config['max_peers']=30;
|
|
||||||
// Testnet, used for development
|
|
||||||
$_config['testnet']=false;
|
|
||||||
// To avoid any problems if other clones are made
|
|
||||||
$_config['coin']="arionum";
|
|
||||||
// maximum transactions accepted from a single peer
|
|
||||||
$_config['peer_max_mempool']=100;
|
|
||||||
// maximum mempool transactions to be rebroadcasted
|
|
||||||
$_config['max_mempool_rebroadcast']=5000;
|
|
||||||
// after how many blocks should the transactions be rebroadcasted
|
|
||||||
$_config['sanity_rebroadcast_height']=30;
|
|
||||||
// each new received transaction is sent to X peers
|
|
||||||
$_config['transaction_propagation_peers']=5;
|
|
||||||
// how many new peers to check from each peer.
|
|
||||||
$_config['max_test_peers']=5;
|
|
||||||
// recheck the last blocks on sanity
|
|
||||||
$_config['sanity_recheck_blocks']=10;
|
|
||||||
// allow others to connect to node api. If set to false, only allowed_hosts are allowed
|
|
||||||
$_config['public_api']=true;
|
|
||||||
// hosts allowed to mine on this node
|
|
||||||
$_config['allowed_hosts']=array("127.0.0.1");
|
|
||||||
// sanity is run every X seconds
|
|
||||||
$_config['sanity_interval']=900;
|
|
||||||
// accept the setting of new hostnames / should be used only if you want to change the hostname
|
|
||||||
$_config['allow_hostname_change']=false;
|
|
||||||
// rebroadcast local transactions on each sanity
|
|
||||||
$_config['sanity_rebroadcast_locals']=true;
|
|
||||||
// write logs to file
|
|
||||||
$_config['enable_logging']=false;
|
|
||||||
// log file, should not be publicly viewable
|
|
||||||
$_config['log_file']="/var/log/aro.log";
|
|
||||||
//log verbosity, default 0, maximum 3
|
|
||||||
$_config['log_verbosity']=0;
|
|
||||||
//will this run as a masternode?
|
|
||||||
$_config['masternode']=false;
|
|
||||||
//masternode public key
|
|
||||||
$_config['masternode_public_key']="";
|
|
||||||
@@ -24,6 +24,10 @@ function san_host($a)
|
|||||||
function api_err($data)
|
function api_err($data)
|
||||||
{
|
{
|
||||||
global $_config;
|
global $_config;
|
||||||
|
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
}
|
||||||
echo json_encode(["status" => "error", "data" => $data, "coin" => $_config['coin']]);
|
echo json_encode(["status" => "error", "data" => $data, "coin" => $_config['coin']]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@@ -32,6 +36,10 @@ function api_err($data)
|
|||||||
function api_echo($data)
|
function api_echo($data)
|
||||||
{
|
{
|
||||||
global $_config;
|
global $_config;
|
||||||
|
|
||||||
|
if (!headers_sent()) {
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
}
|
||||||
echo json_encode(["status" => "ok", "data" => $data, "coin" => $_config['coin']]);
|
echo json_encode(["status" => "ok", "data" => $data, "coin" => $_config['coin']]);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
@@ -39,6 +47,10 @@ function api_echo($data)
|
|||||||
// log function, shows only in cli atm
|
// log function, shows only in cli atm
|
||||||
function _log($data, $verbosity = 0)
|
function _log($data, $verbosity = 0)
|
||||||
{
|
{
|
||||||
|
global $_config;
|
||||||
|
if ($_config['log_verbosity'] < $verbosity) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$date = date("[Y-m-d H:i:s]");
|
$date = date("[Y-m-d H:i:s]");
|
||||||
$trace = debug_backtrace();
|
$trace = debug_backtrace();
|
||||||
$loc = count($trace) - 1;
|
$loc = count($trace) - 1;
|
||||||
@@ -56,7 +68,6 @@ function _log($data, $verbosity = 0)
|
|||||||
if (php_sapi_name() === 'cli') {
|
if (php_sapi_name() === 'cli') {
|
||||||
echo $res;
|
echo $res;
|
||||||
}
|
}
|
||||||
global $_config;
|
|
||||||
if ($_config['enable_logging'] == true && $_config['log_verbosity'] >= $verbosity) {
|
if ($_config['enable_logging'] == true && $_config['log_verbosity'] >= $verbosity) {
|
||||||
@file_put_contents($_config['log_file'], $res, FILE_APPEND);
|
@file_put_contents($_config['log_file'], $res, FILE_APPEND);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
// ARO version
|
// ARO version
|
||||||
define("VERSION", "0.4.1");
|
define("VERSION", "0.4.4");
|
||||||
// Amsterdam timezone by default, should probably be moved to config
|
// Amsterdam timezone by default, should probably be moved to config
|
||||||
date_default_timezone_set("UTC");
|
date_default_timezone_set("UTC");
|
||||||
|
|
||||||
@@ -13,12 +13,15 @@ if (php_sapi_name() !== 'cli' && substr_count($_SERVER['PHP_SELF'], "/") > 1) {
|
|||||||
die("This application should only be run in the main directory /");
|
die("This application should only be run in the main directory /");
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once("include/config.inc.php");
|
require_once __DIR__.'/Exception.php';
|
||||||
require_once("include/db.inc.php");
|
require_once __DIR__.'/config.inc.php';
|
||||||
require_once("include/functions.inc.php");
|
require_once __DIR__.'/db.inc.php';
|
||||||
require_once("include/block.inc.php");
|
require_once __DIR__.'/functions.inc.php';
|
||||||
require_once("include/account.inc.php");
|
require_once __DIR__.'/Blacklist.php';
|
||||||
require_once("include/transaction.inc.php");
|
require_once __DIR__.'/InitialPeers.php';
|
||||||
|
require_once __DIR__.'/block.inc.php';
|
||||||
|
require_once __DIR__.'/account.inc.php';
|
||||||
|
require_once __DIR__.'/transaction.inc.php';
|
||||||
|
|
||||||
if ($_config['db_pass'] == "ENTER-DB-PASS") {
|
if ($_config['db_pass'] == "ENTER-DB-PASS") {
|
||||||
die("Please update your config file and set your db password");
|
die("Please update your config file and set your db password");
|
||||||
@@ -71,13 +74,10 @@ if (file_exists("tmp/db-update")) {
|
|||||||
if($ram<1700000) {
|
if($ram<1700000) {
|
||||||
die("The node requires at least 2 GB of RAM");
|
die("The node requires at least 2 GB of RAM");
|
||||||
}
|
}
|
||||||
if($_config['masternode']==true && $ram<7000000){
|
|
||||||
die("The masternode require at least 8GB of RAM");
|
|
||||||
}
|
|
||||||
$res = unlink("tmp/db-update");
|
$res = unlink("tmp/db-update");
|
||||||
if ($res) {
|
if ($res) {
|
||||||
echo "Updating db schema! Please refresh!\n";
|
echo "Updating db schema! Please refresh!\n";
|
||||||
require_once("include/schema.inc.php");
|
require_once __DIR__.'/schema.inc.php';
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
echo "Could not access the tmp/db-update file. Please give full permissions to this file\n";
|
echo "Could not access the tmp/db-update file. Please give full permissions to this file\n";
|
||||||
|
|||||||
@@ -164,7 +164,10 @@ if ($dbversion == 8) {
|
|||||||
ADD KEY `height` (`height`);");
|
ADD KEY `height` (`height`);");
|
||||||
$dbversion++;
|
$dbversion++;
|
||||||
}
|
}
|
||||||
|
if ($dbversion = 9) {
|
||||||
|
//dev only
|
||||||
|
$dbversion++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// update the db version to the latest one
|
// update the db version to the latest one
|
||||||
|
|||||||
@@ -1,56 +1,83 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Arionum\Blacklist;
|
||||||
|
|
||||||
class Transaction
|
class Transaction
|
||||||
{
|
{
|
||||||
// reverse and remove all transactions from a block
|
// reverse and remove all transactions from a block
|
||||||
public function reverse($block)
|
public function reverse($block)
|
||||||
{
|
{
|
||||||
global $db;
|
global $db;
|
||||||
|
|
||||||
$acc = new Account();
|
$acc = new Account();
|
||||||
$r = $db->run("SELECT * FROM transactions WHERE block=:block ORDER by `version` ASC", [":block" => $block]);
|
$r = $db->run("SELECT * FROM transactions WHERE block=:block ORDER by `version` ASC", [":block" => $block]);
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
|
_log("Reversing transaction $x[id]", 4);
|
||||||
if (empty($x['src'])) {
|
if (empty($x['src'])) {
|
||||||
$x['src'] = $acc->get_address($x['public_key']);
|
$x['src'] = $acc->get_address($x['public_key']);
|
||||||
}
|
}
|
||||||
if ($x['version'] == 2) {
|
if ($x['version'] == 2) {
|
||||||
// payment sent to alias
|
// payment sent to alias
|
||||||
$db->run(
|
$rez=$db->run(
|
||||||
"UPDATE accounts SET balance=balance-:val WHERE alias=:alias",
|
"UPDATE accounts SET balance=balance-:val WHERE alias=:alias",
|
||||||
[":alias" => $x['dst'], ":val" => $x['val']]
|
[":alias" => $x['dst'], ":val" => $x['val']]
|
||||||
);
|
);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Update alias balance minus failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// other type of transactions
|
// other type of transactions
|
||||||
$db->run(
|
|
||||||
|
if ($x['version']!=100&&$x['version']<111) {
|
||||||
|
$rez=$db->run(
|
||||||
"UPDATE accounts SET balance=balance-:val WHERE id=:id",
|
"UPDATE accounts SET balance=balance-:val WHERE id=:id",
|
||||||
[":id" => $x['dst'], ":val" => $x['val']]
|
[":id" => $x['dst'], ":val" => $x['val']]
|
||||||
);
|
);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Update accounts balance minus failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// on version 0 / reward transaction, don't credit anyone
|
// on version 0 / reward transaction, don't credit anyone
|
||||||
if ($x['version'] > 0) {
|
if ($x['version'] > 0 && $x['version']<111) {
|
||||||
$db->run(
|
$rez=$db->run(
|
||||||
"UPDATE accounts SET balance=balance+:val WHERE id=:id",
|
"UPDATE accounts SET balance=balance+:val WHERE id=:id",
|
||||||
[":id" => $x['src'], ":val" => $x['val'] + $x['fee']]
|
[":id" => $x['src'], ":val" => $x['val'] + $x['fee']]
|
||||||
);
|
);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Update account balance plus failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// removing the alias if the alias transaction is reversed
|
// removing the alias if the alias transaction is reversed
|
||||||
if ($x['version']==3) {
|
if ($x['version']==3) {
|
||||||
$db->run(
|
$rez=$db->run(
|
||||||
"UPDATE accounts SET alias=NULL WHERE id=:id",
|
"UPDATE accounts SET alias=NULL WHERE id=:id",
|
||||||
[":id" => $x['src']]
|
[":id" => $x['src']]
|
||||||
);
|
);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Clear alias failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($x['version']>=100&&$x['version']<110&&$x['height']>=80000) {
|
if ($x['version']>=100&&$x['version']<110&&$x['height']>=80000) {
|
||||||
if ($x['version']==100) {
|
if ($x['version']==100) {
|
||||||
$db->run("DELETE FROM masternode WHERE public_key=:public_key", [':public_key'=>$x['public_key']]);
|
$rez=$db->run("DELETE FROM masternode WHERE public_key=:public_key", [':public_key'=>$x['public_key']]);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Delete from masternode failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
} elseif ($x['version']==101) {
|
} elseif ($x['version']==101) {
|
||||||
$db->run(
|
$rez=$db->run(
|
||||||
"UPDATE masternode SET status=1 WHERE public_key=:public_key",
|
"UPDATE masternode SET status=1 WHERE public_key=:public_key",
|
||||||
[':public_key'=>$x['public_key']]
|
[':public_key'=>$x['public_key']]
|
||||||
);
|
);
|
||||||
} elseif ($x['version']==102) {
|
} elseif ($x['version']==102) {
|
||||||
$db->run("UPDATE masternode SET status=0 WHERE public_key=:public_key", [':public_key'=>$x['public_key']]);
|
$rez=$db->run("UPDATE masternode SET status=0 WHERE public_key=:public_key", [':public_key'=>$x['public_key']]);
|
||||||
} elseif ($x['version']==103) {
|
} elseif ($x['version']==103) {
|
||||||
$mnt=$db->row("SELECT height, `message` FROM transactions WHERE version=100 AND public_key=:public_key ORDER by height DESC LIMIT 1", [":public_key"=>$x['public_key']]);
|
$mnt=$db->row("SELECT height, `message` FROM transactions WHERE version=100 AND public_key=:public_key ORDER by height DESC LIMIT 1", [":public_key"=>$x['public_key']]);
|
||||||
$vers=$db->single(
|
$vers=$db->single(
|
||||||
@@ -64,29 +91,43 @@ class Transaction
|
|||||||
$status=0;
|
$status=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
$db->run(
|
$rez=$db->run(
|
||||||
"INSERT into masternode SET `public_key`=:public_key, `height`=:height, `ip`=:ip, `status`=:status",
|
"INSERT into masternode SET `public_key`=:public_key, `height`=:height, `ip`=:ip, `status`=:status",
|
||||||
[":public_key"=>$x['public_key'], ":height"=>$mnt['height'], ":ip"=>$mnt['message'], ":status"=>$status]
|
[":public_key"=>$x['public_key'], ":height"=>$mnt['height'], ":ip"=>$mnt['message'], ":status"=>$status]
|
||||||
);
|
);
|
||||||
$db->run("UPDATE accounts SET balance=balance-100000 WHERE public_key=:public_key", [':public_key'=>$x['public_key']]);
|
if ($rez!=1) {
|
||||||
|
_log("Insert into masternode failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$rez=$db->run("UPDATE accounts SET balance=balance-100000 WHERE public_key=:public_key", [':public_key'=>$x['public_key']]);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Update masternode balance failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// internal masternode history
|
// internal masternode history
|
||||||
if ($x['version']==111) {
|
if ($x['version']==111) {
|
||||||
|
_log("Masternode reverse: $x[message]", 4);
|
||||||
$m=explode(",", $x['message']);
|
$m=explode(",", $x['message']);
|
||||||
|
|
||||||
$db->run(
|
$rez=$db->run(
|
||||||
"UPDATE masternode SET fails=:fails, blacklist=:blacklist, last_won=:last_won WHERE public_key=:public_key",
|
"UPDATE masternode SET fails=:fails, blacklist=:blacklist, last_won=:last_won WHERE public_key=:public_key",
|
||||||
[":public_key"=>$x['public_key'], ":blacklist"=> $m[0], ":fails"=>$m[2], ":last_won"=>$m[1]]
|
[":public_key"=>$x['public_key'], ":blacklist"=> $m[0], ":fails"=>$m[2], ":last_won"=>$m[1]]
|
||||||
);
|
);
|
||||||
|
if ($rez!=1) {
|
||||||
|
_log("Update masternode log failed", 3);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the transactions to mempool
|
// add the transactions to mempool
|
||||||
if ($x['version'] > 0 && $x['version']<=1000) {
|
if ($x['version'] > 0 && $x['version']<=110) {
|
||||||
$this->add_mempool($x);
|
$this->add_mempool($x);
|
||||||
}
|
}
|
||||||
$res = $db->run("DELETE FROM transactions WHERE id=:id", [":id" => $x['id']]);
|
$res = $db->run("DELETE FROM transactions WHERE id=:id", [":id" => $x['id']]);
|
||||||
if ($res != 1) {
|
if ($res != 1) {
|
||||||
|
_log("Delete transaction failed", 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -179,10 +220,17 @@ class Transaction
|
|||||||
public function add_mempool($x, $peer = "")
|
public function add_mempool($x, $peer = "")
|
||||||
{
|
{
|
||||||
global $db;
|
global $db;
|
||||||
|
global $_config;
|
||||||
$block = new Block();
|
$block = new Block();
|
||||||
if ($x['version']>110) {
|
if ($x['version']>110) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($_config['use_official_blacklist']!==false) {
|
||||||
|
if (Blacklist::checkPublicKey($x['public_key']) || Blacklist::checkAddress($x['src'])) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
$current = $block->current();
|
$current = $block->current();
|
||||||
$height = $current['height'];
|
$height = $current['height'];
|
||||||
$x['id'] = san($x['id']);
|
$x['id'] = san($x['id']);
|
||||||
@@ -253,9 +301,9 @@ class Transaction
|
|||||||
//master node deposit
|
//master node deposit
|
||||||
} elseif ($x['version']==103&&$height>=80000) {
|
} elseif ($x['version']==103&&$height>=80000) {
|
||||||
$blk=new Block();
|
$blk=new Block();
|
||||||
$blk->masternode_log($x['public_key'],$height,$block);
|
$blk->masternode_log($x['public_key'], $height, $block);
|
||||||
|
|
||||||
//master node withdrawal
|
//master node withdrawal
|
||||||
} else {
|
} else {
|
||||||
$db->run("UPDATE accounts SET balance=balance+:val WHERE id=:id", [":id" => $x['dst'], ":val" => $x['val']]);
|
$db->run("UPDATE accounts SET balance=balance+:val WHERE id=:id", [":id" => $x['dst'], ":val" => $x['val']]);
|
||||||
}
|
}
|
||||||
@@ -329,7 +377,7 @@ class Transaction
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// internal transactions
|
// internal transactions
|
||||||
if($x['version']>110){
|
if ($x['version']>110) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,6 +423,11 @@ class Transaction
|
|||||||
_log("The Masternode IP is invalid", 3);
|
_log("The Masternode IP is invalid", 3);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
global $db;
|
||||||
|
$existing=$db->single("SELECT COUNT(1) FROM masternode WHERE public_key=:id or ip=:ip", ["id"=>$x['public_key'], ":ip"=>$message]);
|
||||||
|
if ($existing!=0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
12
index.php
12
index.php
@@ -185,6 +185,10 @@ $current = $block->current();
|
|||||||
background-color: #209cee;
|
background-color: #209cee;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
.tag:not(body).is-danger {
|
||||||
|
background-color: #f48f42;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
.tag:not(body).is-success {
|
.tag:not(body).is-success {
|
||||||
background-color: #23d160;
|
background-color: #23d160;
|
||||||
@@ -292,12 +296,20 @@ $current = $block->current();
|
|||||||
<span class="tag is-light"><?= $current['height']; ?></span>
|
<span class="tag is-light"><?= $current['height']; ?></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="control">
|
||||||
|
<div class="tags has-addons">
|
||||||
|
<strong class="tag is-danger">Version</strong>
|
||||||
|
<span class="tag is-light"><?= VERSION; ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<div class="tags has-addons">
|
<div class="tags has-addons">
|
||||||
<strong class="tag is-info">Public API</strong>
|
<strong class="tag is-info">Public API</strong>
|
||||||
<span class="tag is-light"><?= ($_config['public_api']) ? 'yes' : 'no'; ?></span>
|
<span class="tag is-light"><?= ($_config['public_api']) ? 'yes' : 'no'; ?></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control">
|
<div class="control">
|
||||||
<a class="tags is-dark" href="./doc/" target="_blank">
|
<a class="tags is-dark" href="./doc/" target="_blank">
|
||||||
<strong class="tag is-info">Documentation</strong>
|
<strong class="tag is-info">Documentation</strong>
|
||||||
|
|||||||
19
mine.php
19
mine.php
@@ -23,7 +23,7 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
require_once("include/init.inc.php");
|
require_once __DIR__.'/include/init.inc.php';
|
||||||
$block = new Block();
|
$block = new Block();
|
||||||
$acc = new Account();
|
$acc = new Account();
|
||||||
set_time_limit(360);
|
set_time_limit(360);
|
||||||
@@ -56,6 +56,19 @@ if ($q == "info") {
|
|||||||
$argon_threads=1;
|
$argon_threads=1;
|
||||||
$argon_time=1;
|
$argon_time=1;
|
||||||
}
|
}
|
||||||
|
} elseif($current_height>=80458){
|
||||||
|
if($current_height%2==0){
|
||||||
|
$argon_mem=524288;
|
||||||
|
$argon_threads=1;
|
||||||
|
$argon_time=1;
|
||||||
|
} else {
|
||||||
|
$argon_mem=16384;
|
||||||
|
$argon_threads=4;
|
||||||
|
$argon_time=4;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if ($current_height%3==0) {
|
if ($current_height%3==0) {
|
||||||
$argon_mem=524288;
|
$argon_mem=524288;
|
||||||
@@ -67,7 +80,7 @@ if ($q == "info") {
|
|||||||
"SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 1",
|
"SELECT public_key FROM masternode WHERE status=1 AND blacklist<:current AND height<:start ORDER by last_won ASC, public_key ASC LIMIT 1",
|
||||||
[":current"=>$current_height, ":start"=>$current_height-360]
|
[":current"=>$current_height, ":start"=>$current_height-360]
|
||||||
);
|
);
|
||||||
$recommendation="pause";
|
//$recommendation="pause";
|
||||||
if ($winner===false) {
|
if ($winner===false) {
|
||||||
$recommendation="mine";
|
$recommendation="mine";
|
||||||
}
|
}
|
||||||
@@ -105,6 +118,7 @@ if ($q == "info") {
|
|||||||
if ($res) {
|
if ($res) {
|
||||||
//if the new block is generated, propagate it to all peers in background
|
//if the new block is generated, propagate it to all peers in background
|
||||||
$current = $block->current();
|
$current = $block->current();
|
||||||
|
$current['id']=escapeshellarg(san($current['id']));
|
||||||
system("php propagate.php block $current[id] > /dev/null 2>&1 &");
|
system("php propagate.php block $current[id] > /dev/null 2>&1 &");
|
||||||
api_echo("accepted");
|
api_echo("accepted");
|
||||||
}
|
}
|
||||||
@@ -180,6 +194,7 @@ if ($q == "info") {
|
|||||||
if ($res) {
|
if ($res) {
|
||||||
//if the new block is generated, propagate it to all peers in background
|
//if the new block is generated, propagate it to all peers in background
|
||||||
$current = $block->current();
|
$current = $block->current();
|
||||||
|
$current['id']=escapeshellarg(san($current['id']));
|
||||||
system("php propagate.php block $current[id] > /dev/null 2>&1 &");
|
system("php propagate.php block $current[id] > /dev/null 2>&1 &");
|
||||||
api_echo("accepted");
|
api_echo("accepted");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
10
peer.php
10
peer.php
@@ -23,7 +23,9 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
require_once("include/init.inc.php");
|
require_once __DIR__.'/include/init.inc.php';
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
$trx = new Transaction();
|
$trx = new Transaction();
|
||||||
$block = new Block();
|
$block = new Block();
|
||||||
$q = $_GET['q'];
|
$q = $_GET['q'];
|
||||||
@@ -150,6 +152,7 @@ if ($q == "peer") {
|
|||||||
// rebroadcast the transaction to some peers unless the transaction is smaller than the average size of transactions in mempool - protect against garbage data flooding
|
// rebroadcast the transaction to some peers unless the transaction is smaller than the average size of transactions in mempool - protect against garbage data flooding
|
||||||
$res = $db->row("SELECT COUNT(1) as c, sum(val) as v FROM mempool ", [":src" => $data['src']]);
|
$res = $db->row("SELECT COUNT(1) as c, sum(val) as v FROM mempool ", [":src" => $data['src']]);
|
||||||
if ($res['c'] < $_config['max_mempool_rebroadcast'] && $res['v'] / $res['c'] < $data['val']) {
|
if ($res['c'] < $_config['max_mempool_rebroadcast'] && $res['v'] / $res['c'] < $data['val']) {
|
||||||
|
$data['id']=escapeshellarg(san($data['id']));
|
||||||
system("php propagate.php transaction '$data[id]' > /dev/null 2>&1 &");
|
system("php propagate.php transaction '$data[id]' > /dev/null 2>&1 &");
|
||||||
}
|
}
|
||||||
api_echo("transaction-ok");
|
api_echo("transaction-ok");
|
||||||
@@ -185,6 +188,7 @@ if ($q == "peer") {
|
|||||||
if ($accept_new) {
|
if ($accept_new) {
|
||||||
// if the new block is accepted, run a microsanity to sync it
|
// if the new block is accepted, run a microsanity to sync it
|
||||||
_log('['.$ip."] Starting microsanity - $data[height]");
|
_log('['.$ip."] Starting microsanity - $data[height]");
|
||||||
|
$ip=escapeshellarg($ip);
|
||||||
system("php sanity.php microsanity '$ip' > /dev/null 2>&1 &");
|
system("php sanity.php microsanity '$ip' > /dev/null 2>&1 &");
|
||||||
api_echo("microsanity");
|
api_echo("microsanity");
|
||||||
} else {
|
} else {
|
||||||
@@ -200,7 +204,7 @@ if ($q == "peer") {
|
|||||||
if (!$pr) {
|
if (!$pr) {
|
||||||
api_err("block-too-old");
|
api_err("block-too-old");
|
||||||
}
|
}
|
||||||
$peer_host = base58_encode($pr['hostname']);
|
$peer_host = escapeshellcmd(base58_encode($pr['hostname']));
|
||||||
$pr['ip'] = escapeshellcmd(san_ip($pr['ip']));
|
$pr['ip'] = escapeshellcmd(san_ip($pr['ip']));
|
||||||
system("php propagate.php block current '$peer_host' '$pr[ip]' > /dev/null 2>&1 &");
|
system("php propagate.php block current '$peer_host' '$pr[ip]' > /dev/null 2>&1 &");
|
||||||
_log('['.$ip."] block too old, sending our current block - $data[height]");
|
_log('['.$ip."] block too old, sending our current block - $data[height]");
|
||||||
@@ -243,6 +247,7 @@ if ($q == "peer") {
|
|||||||
_log('['.$ip."] block ok, repropagating - $data[height]");
|
_log('['.$ip."] block ok, repropagating - $data[height]");
|
||||||
|
|
||||||
// send it to all our peers
|
// send it to all our peers
|
||||||
|
$data['id']=escapeshellcmd(san($data['id']));
|
||||||
system("php propagate.php block '$data[id]' all all linear > /dev/null 2>&1 &");
|
system("php propagate.php block '$data[id]' all all linear > /dev/null 2>&1 &");
|
||||||
api_echo("block-ok");
|
api_echo("block-ok");
|
||||||
} // return the current block, used in syncing
|
} // return the current block, used in syncing
|
||||||
@@ -252,7 +257,6 @@ elseif ($q == "currentBlock") {
|
|||||||
} // return a specific block, used in syncing
|
} // return a specific block, used in syncing
|
||||||
elseif ($q == "getBlock") {
|
elseif ($q == "getBlock") {
|
||||||
$height = intval($data['height']);
|
$height = intval($data['height']);
|
||||||
|
|
||||||
$export = $block->export("", $height);
|
$export = $block->export("", $height);
|
||||||
if (!$export) {
|
if (!$export) {
|
||||||
api_err("invalid-block");
|
api_err("invalid-block");
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|||||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
set_time_limit(360);
|
set_time_limit(360);
|
||||||
require_once("include/init.inc.php");
|
require_once __DIR__.'/include/init.inc.php';
|
||||||
$block = new Block();
|
$block = new Block();
|
||||||
|
|
||||||
$type = san($argv[1]);
|
$type = san($argv[1]);
|
||||||
@@ -69,9 +69,13 @@ if ((empty($peer) || $peer == 'all') && $type == "block") {
|
|||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
if($x['hostname']==$_config['hostname']) continue;
|
if($x['hostname']==$_config['hostname']) continue;
|
||||||
// encode the hostname in base58 and sanitize the IP to avoid any second order shell injections
|
// encode the hostname in base58 and sanitize the IP to avoid any second order shell injections
|
||||||
$host = base58_encode($x['hostname']);
|
$host = escapeshellcmd(base58_encode($x['hostname']));
|
||||||
$ip = filter_var($x['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE);
|
$ip = escapeshellcmd(filter_var($x['ip'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE));
|
||||||
// fork a new process to send the blocks async
|
// fork a new process to send the blocks async
|
||||||
|
$type=escapeshellcmd(san($type));
|
||||||
|
$id=escapeshellcmd(san($id));
|
||||||
|
|
||||||
|
|
||||||
if ($debug) {
|
if ($debug) {
|
||||||
system("php propagate.php '$type' '$id' '$host' '$ip' debug");
|
system("php propagate.php '$type' '$id' '$host' '$ip' debug");
|
||||||
} elseif ($linear) {
|
} elseif ($linear) {
|
||||||
@@ -166,7 +170,8 @@ if ($type == "transaction") {
|
|||||||
if ($data['peer'] == "local") {
|
if ($data['peer'] == "local") {
|
||||||
$r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP()");
|
$r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP()");
|
||||||
} else {
|
} else {
|
||||||
$r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP() AND reserve=0 ORDER by RAND() LIMIT ".intval($_config['transaction_propagation_peers']));
|
|
||||||
|
$r = $db->run("SELECT hostname FROM peers WHERE blacklisted < UNIX_TIMESTAMP() AND reserve=0 ORDER by RAND() LIMIT :limit",["limit"=>intval($_config['transaction_propagation_peers'])]);
|
||||||
}
|
}
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
$res = peer_post($x['hostname']."/peer.php?q=submitTransaction", $data);
|
$res = peer_post($x['hostname']."/peer.php?q=submitTransaction", $data);
|
||||||
|
|||||||
268
sanity.php
268
sanity.php
@@ -23,6 +23,9 @@ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|||||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
||||||
OR OTHER DEALINGS IN THE SOFTWARE.
|
OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
const SANITY_LOCK_PATH = __DIR__.'/tmp/sanity-lock';
|
||||||
|
|
||||||
set_time_limit(0);
|
set_time_limit(0);
|
||||||
error_reporting(0);
|
error_reporting(0);
|
||||||
|
|
||||||
@@ -31,8 +34,10 @@ if (php_sapi_name() !== 'cli') {
|
|||||||
die("This should only be run as cli");
|
die("This should only be run as cli");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_once __DIR__.'/include/init.inc.php';
|
||||||
|
|
||||||
// make sure there's only a single sanity process running at the same time
|
// make sure there's only a single sanity process running at the same time
|
||||||
if (file_exists("tmp/sanity-lock")) {
|
if (file_exists(SANITY_LOCK_PATH)) {
|
||||||
$ignore_lock = false;
|
$ignore_lock = false;
|
||||||
if ($argv[1] == "force") {
|
if ($argv[1] == "force") {
|
||||||
$res = intval(shell_exec("ps aux|grep sanity.php|grep -v grep|wc -l"));
|
$res = intval(shell_exec("ps aux|grep sanity.php|grep -v grep|wc -l"));
|
||||||
@@ -40,17 +45,20 @@ if (file_exists("tmp/sanity-lock")) {
|
|||||||
$ignore_lock = true;
|
$ignore_lock = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$pid_time = filemtime("tmp/sanity-lock");
|
$pid_time = filemtime(SANITY_LOCK_PATH);
|
||||||
// if the process died, restart after 1day
|
|
||||||
if (time() - $pid_time > 86400) {
|
// If the process died, restart after 10 times the sanity interval
|
||||||
@unlink("tmp/sanity-lock");
|
if (time() - $pid_time > ($_config['sanity_interval'] ?? 900 * 10)) {
|
||||||
|
@unlink(SANITY_LOCK_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$ignore_lock) {
|
if (!$ignore_lock) {
|
||||||
die("Sanity lock in place");
|
die("Sanity lock in place".PHP_EOL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the new sanity lock
|
// set the new sanity lock
|
||||||
$lock = fopen("tmp/sanity-lock", "w");
|
$lock = fopen(SANITY_LOCK_PATH, "w");
|
||||||
fclose($lock);
|
fclose($lock);
|
||||||
$arg = trim($argv[1]);
|
$arg = trim($argv[1]);
|
||||||
$arg2 = trim($argv[2]);
|
$arg2 = trim($argv[2]);
|
||||||
@@ -60,13 +68,15 @@ if ($arg != "microsanity") {
|
|||||||
sleep(3);
|
sleep(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($argv[1]=="dev") {
|
||||||
require_once("include/init.inc.php");
|
error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT & ~E_NOTICE);
|
||||||
|
ini_set("display_errors", "on");
|
||||||
|
}
|
||||||
|
|
||||||
// the sanity can't run without the schema being installed
|
// the sanity can't run without the schema being installed
|
||||||
if ($_config['dbversion'] < 2) {
|
if ($_config['dbversion'] < 2) {
|
||||||
die("DB schema not created");
|
die("DB schema not created");
|
||||||
@unlink("tmp/sanity-lock");
|
@unlink(SANITY_LOCK_PATH);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,6 +86,11 @@ $block = new Block();
|
|||||||
$acc = new Account();
|
$acc = new Account();
|
||||||
$current = $block->current();
|
$current = $block->current();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// bootstrapping the initial sync
|
// bootstrapping the initial sync
|
||||||
if ($current['height']==1) {
|
if ($current['height']==1) {
|
||||||
echo "Bootstrapping!\n";
|
echo "Bootstrapping!\n";
|
||||||
@@ -224,7 +239,7 @@ if ($arg == "microsanity" && !empty($arg2)) {
|
|||||||
_log("Synced block from $host - $b[height] $b[difficulty]");
|
_log("Synced block from $host - $b[height] $b[difficulty]");
|
||||||
} while (0);
|
} while (0);
|
||||||
|
|
||||||
@unlink("tmp/sanity-lock");
|
@unlink(SANITY_LOCK_PATH);
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,8 +263,8 @@ $total_active_peers = 0;
|
|||||||
// checking peers
|
// checking peers
|
||||||
|
|
||||||
// delete the dead peers
|
// delete the dead peers
|
||||||
$db->run("DELETE from peers WHERE fails>100 OR stuckfail>200");
|
$db->run("DELETE from peers WHERE fails>100 OR stuckfail>100");
|
||||||
$r = $db->run("SELECT id,hostname,stuckfail,fails FROM peers WHERE reserve=0 AND blacklisted<UNIX_TIMESTAMP()");
|
$r = $db->run("SELECT id,hostname,stuckfail,fails FROM peers WHERE reserve=0 AND blacklisted<UNIX_TIMESTAMP() LIMIT 50");
|
||||||
|
|
||||||
$total_peers = count($r);
|
$total_peers = count($r);
|
||||||
|
|
||||||
@@ -257,16 +272,20 @@ $peered = [];
|
|||||||
// if we have no peers, get the seed list from the official site
|
// if we have no peers, get the seed list from the official site
|
||||||
if ($total_peers == 0 && $_config['testnet'] == false) {
|
if ($total_peers == 0 && $_config['testnet'] == false) {
|
||||||
$i = 0;
|
$i = 0;
|
||||||
echo "No peers found. Attempting to get peers from arionum.com\n";
|
echo 'No peers found. Attempting to get peers from the initial list.'.PHP_EOL;
|
||||||
$f = file("https://www.arionum.com/peers.txt");
|
|
||||||
shuffle($f);
|
$initialPeers = new \Arionum\Node\InitialPeers($_config['initial_peer_list'] ?? []);
|
||||||
// we can't connect to arionum.com
|
|
||||||
if (count($f) < 2) {
|
try {
|
||||||
@unlink("tmp/sanity-lock");
|
$peers = $initialPeers->getAll();
|
||||||
die("Could not connect to arionum.com! Will try later!\n");
|
} catch (\Arionum\Node\Exception $e) {
|
||||||
|
@unlink(SANITY_LOCK_PATH);
|
||||||
|
die($e->getMessage().PHP_EOL);
|
||||||
}
|
}
|
||||||
foreach ($f as $peer) {
|
|
||||||
//peer with all until max_peers, this will ask them to send a peering request to our peer.php where we add their peer to the db.
|
foreach ($peers as $peer) {
|
||||||
|
// Peer with all until max_peers
|
||||||
|
// This will ask them to send a peering request to our peer.php where we add their peer to the db.
|
||||||
$peer = trim(san_host($peer));
|
$peer = trim(san_host($peer));
|
||||||
$bad_peers = ["127.", "localhost", "10.", "192.168.","172.16.","172.17.","172.18.","172.19.","172.20.","172.21.","172.22.","172.23.","172.24.","172.25.","172.26.","172.27.","172.28.","172.29.","172.30.","172.31."];
|
$bad_peers = ["127.", "localhost", "10.", "192.168.","172.16.","172.17.","172.18.","172.19.","172.20.","172.21.","172.22.","172.23.","172.24.","172.25.","172.26.","172.27.","172.28.","172.29.","172.30.","172.31."];
|
||||||
|
|
||||||
@@ -288,7 +307,15 @@ if ($total_peers == 0 && $_config['testnet'] == false) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$peered[$pid] = 1;
|
$peered[$pid] = 1;
|
||||||
$res = peer_post($peer."/peer.php?q=peer", ["hostname" => $_config['hostname'], "repeer" => 1]);
|
|
||||||
|
if($_config['passive_peering'] == true){
|
||||||
|
// does not peer, just add it to DB in passive mode
|
||||||
|
$db->run("INSERT into peers set hostname=:hostname, ping=0, reserve=0,ip=:ip",[":hostname"=>$peer, ":ip"=>md5($peer)]);
|
||||||
|
$res=true;
|
||||||
|
} else {
|
||||||
|
// forces the other node to peer with us.
|
||||||
|
$res = peer_post($peer."/peer.php?q=peer", ["hostname" => $_config['hostname'], "repeer" => 1]);
|
||||||
|
}
|
||||||
if ($res !== false) {
|
if ($res !== false) {
|
||||||
$i++;
|
$i++;
|
||||||
echo "Peering OK - $peer\n";
|
echo "Peering OK - $peer\n";
|
||||||
@@ -304,75 +331,75 @@ if ($total_peers == 0 && $_config['testnet'] == false) {
|
|||||||
$total_peers = count($r);
|
$total_peers = count($r);
|
||||||
if ($total_peers == 0) {
|
if ($total_peers == 0) {
|
||||||
// something went wrong, could not add any peers -> exit
|
// something went wrong, could not add any peers -> exit
|
||||||
@unlink("tmp/sanity-lock");
|
@unlink(SANITY_LOCK_PATH);
|
||||||
die("Could not peer to any peers! Please check internet connectivity!\n");
|
die("Could not peer to any peers! Please check internet connectivity!\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// contact all the active peers
|
// contact all the active peers
|
||||||
|
$i = 0;
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
_log("Contacting peer $x[hostname]");
|
_log("Contacting peer $x[hostname]");
|
||||||
$url = $x['hostname']."/peer.php?q=";
|
$url = $x['hostname']."/peer.php?q=";
|
||||||
// get their peers list
|
// get their peers list
|
||||||
$data = peer_post($url."getPeers", [], 5);
|
if ($_config['get_more_peers']==true && $_config['passive_peering']!=true) {
|
||||||
if ($data === false) {
|
$data = peer_post($url."getPeers", [], 5);
|
||||||
_log("Peer $x[hostname] unresponsive");
|
if ($data === false) {
|
||||||
// if the peer is unresponsive, mark it as failed and blacklist it for a while
|
_log("Peer $x[hostname] unresponsive");
|
||||||
$db->run(
|
// if the peer is unresponsive, mark it as failed and blacklist it for a while
|
||||||
|
$db->run(
|
||||||
"UPDATE peers SET fails=fails+1, blacklisted=UNIX_TIMESTAMP()+((fails+1)*3600) WHERE id=:id",
|
"UPDATE peers SET fails=fails+1, blacklisted=UNIX_TIMESTAMP()+((fails+1)*3600) WHERE id=:id",
|
||||||
[":id" => $x['id']]
|
[":id" => $x['id']]
|
||||||
);
|
);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
$i = 0;
|
|
||||||
foreach ($data as $peer) {
|
|
||||||
// store the hostname as md5 hash, for easier checking
|
|
||||||
$peer['hostname'] = san_host($peer['hostname']);
|
|
||||||
$peer['ip'] = san_ip($peer['ip']);
|
|
||||||
$pid = md5($peer['hostname']);
|
|
||||||
// do not peer if we are already peered
|
|
||||||
if ($peered[$pid] == 1) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$peered[$pid] = 1;
|
foreach ($data as $peer) {
|
||||||
$bad_peers = ["127.", "localhost", "10.", "192.168.","172.16.","172.17.","172.18.","172.19.","172.20.","172.21.","172.22.","172.23.","172.24.","172.25.","172.26.","172.27.","172.28.","172.29.","172.30.","172.31."];
|
// store the hostname as md5 hash, for easier checking
|
||||||
$tpeer=str_replace(["https://","http://","//"], "", $peer['hostname']);
|
$peer['hostname'] = san_host($peer['hostname']);
|
||||||
foreach ($bad_peers as $bp) {
|
$peer['ip'] = san_ip($peer['ip']);
|
||||||
if (strpos($tpeer, $bp)===0) {
|
$pid = md5($peer['hostname']);
|
||||||
|
// do not peer if we are already peered
|
||||||
|
if ($peered[$pid] == 1) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
$peered[$pid] = 1;
|
||||||
// if it's our hostname, ignore
|
$bad_peers = ["127.", "localhost", "10.", "192.168.","172.16.","172.17.","172.18.","172.19.","172.20.","172.21.","172.22.","172.23.","172.24.","172.25.","172.26.","172.27.","172.28.","172.29.","172.30.","172.31."];
|
||||||
if ($peer['hostname'] == $_config['hostname']) {
|
$tpeer=str_replace(["https://","http://","//"], "", $peer['hostname']);
|
||||||
continue;
|
foreach ($bad_peers as $bp) {
|
||||||
}
|
if (strpos($tpeer, $bp)===0) {
|
||||||
// if invalid hostname, ignore
|
continue;
|
||||||
if (!filter_var($peer['hostname'], FILTER_VALIDATE_URL)) {
|
}
|
||||||
continue;
|
}
|
||||||
}
|
// if it's our hostname, ignore
|
||||||
// make sure there's no peer in db with this ip or hostname
|
if ($peer['hostname'] == $_config['hostname']) {
|
||||||
if (!$db->single(
|
continue;
|
||||||
|
}
|
||||||
|
// if invalid hostname, ignore
|
||||||
|
if (!filter_var($peer['hostname'], FILTER_VALIDATE_URL)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// make sure there's no peer in db with this ip or hostname
|
||||||
|
if (!$db->single(
|
||||||
"SELECT COUNT(1) FROM peers WHERE ip=:ip or hostname=:hostname",
|
"SELECT COUNT(1) FROM peers WHERE ip=:ip or hostname=:hostname",
|
||||||
[":ip" => $peer['ip'], ":hostname" => $peer['hostname']]
|
[":ip" => $peer['ip'], ":hostname" => $peer['hostname']]
|
||||||
)) {
|
)) {
|
||||||
$i++;
|
$i++;
|
||||||
// check a max_test_peers number of peers from each peer
|
// check a max_test_peers number of peers from each peer
|
||||||
if ($i > $_config['max_test_peers']) {
|
if ($i > $_config['max_test_peers']) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$peer['hostname'] = filter_var($peer['hostname'], FILTER_SANITIZE_URL);
|
$peer['hostname'] = filter_var($peer['hostname'], FILTER_SANITIZE_URL);
|
||||||
// peer with each one
|
// peer with each one
|
||||||
_log("Trying to peer with recommended peer: $peer[hostname]");
|
_log("Trying to peer with recommended peer: $peer[hostname]");
|
||||||
$test = peer_post($peer['hostname']."/peer.php?q=peer", ["hostname" => $_config['hostname']], 5);
|
$test = peer_post($peer['hostname']."/peer.php?q=peer", ["hostname" => $_config['hostname']], 5);
|
||||||
if ($test !== false) {
|
if ($test !== false) {
|
||||||
$total_peers++;
|
$total_peers++;
|
||||||
echo "Peered with: $peer[hostname]\n";
|
echo "Peered with: $peer[hostname]\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// get the current block and check it's blockchain
|
// get the current block and check it's blockchain
|
||||||
$data = peer_post($url."currentBlock", [], 5);
|
$data = peer_post($url."currentBlock", [], 5);
|
||||||
if ($data === false) {
|
if ($data === false) {
|
||||||
@@ -441,7 +468,7 @@ echo "Most common: $most_common\n";
|
|||||||
echo "Most common block: $most_common_size\n";
|
echo "Most common block: $most_common_size\n";
|
||||||
echo "Max height: $largest_height\n";
|
echo "Max height: $largest_height\n";
|
||||||
echo "Current block: $current[height]\n";
|
echo "Current block: $current[height]\n";
|
||||||
|
$block_parse_failed=false;
|
||||||
// if we're not on the largest height
|
// if we're not on the largest height
|
||||||
if ($current['height'] < $largest_height && $largest_height > 1) {
|
if ($current['height'] < $largest_height && $largest_height > 1) {
|
||||||
// start sanity sync / block all other transactions/blocks
|
// start sanity sync / block all other transactions/blocks
|
||||||
@@ -475,17 +502,17 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} elseif ($data['id'] != $current['id'] && $data['id'] != $most_common) {
|
} elseif ($data['id'] != $current['id'] && $data['id'] != $most_common) {
|
||||||
//if we're not on the same blockchain and also it's not the most common, verify all the blocks on on this blockchain starting at current-10 until current
|
//if we're not on the same blockchain and also it's not the most common, verify all the blocks on on this blockchain starting at current-30 until current
|
||||||
$invalid = false;
|
$invalid = false;
|
||||||
$last_good = $current['height'];
|
$last_good = $current['height'];
|
||||||
for ($i = $current['height'] - 10; $i < $current['height']; $i++) {
|
for ($i = $current['height'] - 30; $i < $current['height']; $i++) {
|
||||||
$data = peer_post($url."getBlock", ["height" => $i]);
|
$data = peer_post($url."getBlock", ["height" => $i]);
|
||||||
if ($data === false) {
|
if ($data === false) {
|
||||||
$invalid = true;
|
$invalid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
$ext = $block->get($i);
|
$ext = $block->get($i);
|
||||||
if ($i == $current['height'] - 10 && $ext['id'] != $data['id']) {
|
if ($i == $current['height'] - 30 && $ext['id'] != $data['id']) {
|
||||||
$invalid = true;
|
$invalid = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -494,7 +521,7 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
|
|||||||
$last_good = $i;
|
$last_good = $i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($last_good==$current['height']-1&&$last_good%3==2) {
|
if ($last_good==$current['height']-1) {
|
||||||
$block->pop(1);
|
$block->pop(1);
|
||||||
}
|
}
|
||||||
// if last 10 blocks are good, verify all the blocks
|
// if last 10 blocks are good, verify all the blocks
|
||||||
@@ -510,7 +537,7 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
|
|||||||
}
|
}
|
||||||
// check if the block mining data is correct
|
// check if the block mining data is correct
|
||||||
for ($i = $last_good + 1; $i <= $largest_height; $i++) {
|
for ($i = $last_good + 1; $i <= $largest_height; $i++) {
|
||||||
if (($i-1)%3==2) {
|
if (($i-1)%3==2&&$cblock[$i - 1]['height']<80458) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!$block->mine(
|
if (!$block->mine(
|
||||||
@@ -553,6 +580,7 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
|
|||||||
$b['height'] = san($b['height']);
|
$b['height'] = san($b['height']);
|
||||||
|
|
||||||
if (!$block->check($b)) {
|
if (!$block->check($b)) {
|
||||||
|
$block_parse_failed=true;
|
||||||
_log("Block check: could not add block - $b[id] - $b[height]");
|
_log("Block check: could not add block - $b[id] - $b[height]");
|
||||||
$good_peer = false;
|
$good_peer = false;
|
||||||
break;
|
break;
|
||||||
@@ -569,6 +597,7 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
|
|||||||
$b['argon']
|
$b['argon']
|
||||||
);
|
);
|
||||||
if (!$res) {
|
if (!$res) {
|
||||||
|
$block_parse_failed=true;
|
||||||
_log("Block add: could not add block - $b[id] - $b[height]");
|
_log("Block add: could not add block - $b[id] - $b[height]");
|
||||||
$good_peer = false;
|
$good_peer = false;
|
||||||
break;
|
break;
|
||||||
@@ -585,6 +614,70 @@ if ($current['height'] < $largest_height && $largest_height > 1) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$resyncing=false;
|
||||||
|
if ($block_parse_failed==true&&$current['date']<time()-(3600*24)) {
|
||||||
|
_log("Rechecking reward transactions");
|
||||||
|
$current = $block->current();
|
||||||
|
$rwpb=$db->single("SELECT COUNT(1) FROM transactions WHERE version=0 AND message=''");
|
||||||
|
if ($rwpb!=$current['height']) {
|
||||||
|
$failed=$db->single("SELECT blocks.height FROM blocks LEFT JOIN transactions ON transactions.block=blocks.id and transactions.version=0 and transactions.message='' WHERE transactions.height is NULL ORDER by blocks.height ASC LIMIT 1");
|
||||||
|
if ($failed>1) {
|
||||||
|
_log("Found failed block - $faield");
|
||||||
|
$block->delete($failed);
|
||||||
|
$block_parse_failed==false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($block_parse_failed==true||$argv[1]=="resync") {
|
||||||
|
$last_resync=$db->single("SELECT val FROM config WHERE cfg='last_resync'");
|
||||||
|
if ($last_resync<time()-(3600*24)||$argv[1]=="resync") {
|
||||||
|
if ($current['date']<time()-(3600*72)||$argv[1]=="resync") {
|
||||||
|
$to_remove=3000;
|
||||||
|
if (intval($argv[2])>0) {
|
||||||
|
$to_remove=intval($argv[2]);
|
||||||
|
}
|
||||||
|
_log("Removing $to_remove blocks, the blockchain is stale.");
|
||||||
|
$block->pop(to_remove);
|
||||||
|
$resyncing=true;
|
||||||
|
} elseif ($current['date']<time()-(3600*24)) {
|
||||||
|
_log("Removing 200 blocks, the blockchain is stale.");
|
||||||
|
$block->pop(200);
|
||||||
|
|
||||||
|
$resyncing=true;
|
||||||
|
}
|
||||||
|
if ($resyncing==true) {
|
||||||
|
_log("Resyncing accounts");
|
||||||
|
$db->run("INSERT into config SET val=UNIX_TIMESTAMP(), cfg='last_resync' ON DUPLICATE KEY UPDATE val=UNIX_TIMESTAMP()");
|
||||||
|
$db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE");
|
||||||
|
|
||||||
|
$r=$db->run("SELECT * FROM accounts");
|
||||||
|
foreach ($r as $x) {
|
||||||
|
$alias=$x['alias'];
|
||||||
|
if (empty($alias)) {
|
||||||
|
$alias="A";
|
||||||
|
}
|
||||||
|
$rec=$db->single("SELECT SUM(val) FROM transactions WHERE (dst=:id or dst=:alias) AND (height<80000 OR (version!=100 AND version!=103)) and version<111", [":id"=>$x['id'], ":alias"=>$alias]);
|
||||||
|
$spent=$db->single("SELECT SUM(val+fee) FROM transactions WHERE public_key=:pub AND version>0", [":pub"=>$x['public_key']]);
|
||||||
|
if ($spent==false) {
|
||||||
|
$spent=0;
|
||||||
|
}
|
||||||
|
$balance=round(($rec-$spent), 8);
|
||||||
|
if ($x['balance']!=$balance) {
|
||||||
|
// echo "rec: $rec, spent: $spent, bal: $x[balance], should be: $balance - $x[id] $x[public_key]\n";
|
||||||
|
if (trim($argv[2])!="check") {
|
||||||
|
$db->run("UPDATE accounts SET balance=:bal WHERE id=:id", [":id"=>$x['id'], ":bal"=>$balance]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$current = $block->current();
|
||||||
|
$db->run("DELETE FROM masternode WHERE height>:h", [":h"=>$current['height']]);
|
||||||
|
$db->exec("UNLOCK TABLES");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$db->run("UPDATE config SET val=0 WHERE cfg='sanity_sync'", [":time" => $t]);
|
$db->run("UPDATE config SET val=0 WHERE cfg='sanity_sync'", [":time" => $t]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -594,14 +687,14 @@ $db->run("DELETE FROM `mempool` WHERE `date` < UNIX_TIMESTAMP()-(3600*24*14)");
|
|||||||
|
|
||||||
|
|
||||||
//rebroadcasting local transactions
|
//rebroadcasting local transactions
|
||||||
if ($_config['sanity_rebroadcast_locals'] == true) {
|
if ($_config['sanity_rebroadcast_locals'] == true && $_config['disable_repropagation'] == false) {
|
||||||
$r = $db->run(
|
$r = $db->run(
|
||||||
"SELECT id FROM mempool WHERE height>=:current and peer='local' order by `height` asc LIMIT 20",
|
"SELECT id FROM mempool WHERE height>=:current and peer='local' order by `height` asc LIMIT 20",
|
||||||
[":current" => $current['height']]
|
[":current" => $current['height']]
|
||||||
);
|
);
|
||||||
_log("Rebroadcasting local transactions - ".count($r));
|
_log("Rebroadcasting local transactions - ".count($r));
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
$x['id'] = san($x['id']);
|
$x['id'] = escapeshellarg(san($x['id'])); // i know it's redundant due to san(), but some people are too scared of any exec
|
||||||
system("php propagate.php transaction $x[id] > /dev/null 2>&1 &");
|
system("php propagate.php transaction $x[id] > /dev/null 2>&1 &");
|
||||||
$db->run(
|
$db->run(
|
||||||
"UPDATE mempool SET height=:current WHERE id=:id",
|
"UPDATE mempool SET height=:current WHERE id=:id",
|
||||||
@@ -611,21 +704,22 @@ if ($_config['sanity_rebroadcast_locals'] == true) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//rebroadcasting transactions
|
//rebroadcasting transactions
|
||||||
$forgotten = $current['height'] - $_config['sanity_rebroadcast_height'];
|
if ($_config['disable_repropagation'] == false) {
|
||||||
$r = $db->run(
|
$forgotten = $current['height'] - $_config['sanity_rebroadcast_height'];
|
||||||
|
$r = $db->run(
|
||||||
"SELECT id FROM mempool WHERE height<:forgotten ORDER by val DESC LIMIT 10",
|
"SELECT id FROM mempool WHERE height<:forgotten ORDER by val DESC LIMIT 10",
|
||||||
[":forgotten" => $forgotten]
|
[":forgotten" => $forgotten]
|
||||||
);
|
);
|
||||||
|
|
||||||
_log("Rebroadcasting external transactions - ".count($r));
|
_log("Rebroadcasting external transactions - ".count($r));
|
||||||
|
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
$x['id'] = san($x['id']);
|
$x['id'] = escapeshellarg(san($x['id'])); // i know it's redundant due to san(), but some people are too scared of any exec
|
||||||
system("php propagate.php transaction $x[id] > /dev/null 2>&1 &");
|
system("php propagate.php transaction $x[id] > /dev/null 2>&1 &");
|
||||||
$db->run("UPDATE mempool SET height=:current WHERE id=:id", [":id" => $x['id'], ":current" => $current['height']]);
|
$db->run("UPDATE mempool SET height=:current WHERE id=:id", [":id" => $x['id'], ":current" => $current['height']]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//add new peers if there aren't enough active
|
//add new peers if there aren't enough active
|
||||||
if ($total_peers < $_config['max_peers'] * 0.7) {
|
if ($total_peers < $_config['max_peers'] * 0.7) {
|
||||||
$res = $_config['max_peers'] - $total_peers;
|
$res = $_config['max_peers'] - $total_peers;
|
||||||
@@ -633,7 +727,7 @@ if ($total_peers < $_config['max_peers'] * 0.7) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//random peer check
|
//random peer check
|
||||||
$r = $db->run("SELECT * FROM peers WHERE blacklisted<UNIX_TIMESTAMP() and reserve=1 LIMIT ".$_config['max_test_peers']);
|
$r = $db->run("SELECT * FROM peers WHERE blacklisted<UNIX_TIMESTAMP() and reserve=1 LIMIT :limit", [":limit"=>intval($_config['max_test_peers'])]);
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
$url = $x['hostname']."/peer.php?q=";
|
$url = $x['hostname']."/peer.php?q=";
|
||||||
$data = peer_post($url."ping", [], 5);
|
$data = peer_post($url."ping", [], 5);
|
||||||
@@ -710,4 +804,4 @@ if ($_config['sanity_recheck_blocks'] > 0 && $_config['testnet'] == false) {
|
|||||||
|
|
||||||
_log("Finishing sanity");
|
_log("Finishing sanity");
|
||||||
|
|
||||||
@unlink("tmp/sanity-lock");
|
@unlink(SANITY_LOCK_PATH);
|
||||||
|
|||||||
3
tmp/.gitignore
vendored
Normal file
3
tmp/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
||||||
|
!db-update
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
4.0.2
|
||||||
|
|||||||
156
util.php
156
util.php
@@ -29,7 +29,7 @@ if (php_sapi_name() !== 'cli') {
|
|||||||
die("This should only be run as cli");
|
die("This should only be run as cli");
|
||||||
}
|
}
|
||||||
|
|
||||||
require_once("include/init.inc.php");
|
require_once __DIR__.'/include/init.inc.php';
|
||||||
$cmd = trim($argv[1]);
|
$cmd = trim($argv[1]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,6 +43,10 @@ $cmd = trim($argv[1]);
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
if ($cmd == 'clean') {
|
if ($cmd == 'clean') {
|
||||||
|
if (file_exists("tmp/sanity-lock")) {
|
||||||
|
die("Sanity running. Wait for it to finish");
|
||||||
|
}
|
||||||
|
touch("tmp/sanity-lock");
|
||||||
$db->run("SET foreign_key_checks=0;");
|
$db->run("SET foreign_key_checks=0;");
|
||||||
$tables = ["accounts", "transactions", "mempool", "masternode","blocks"];
|
$tables = ["accounts", "transactions", "mempool", "masternode","blocks"];
|
||||||
foreach ($tables as $table) {
|
foreach ($tables as $table) {
|
||||||
@@ -51,6 +55,7 @@ if ($cmd == 'clean') {
|
|||||||
$db->run("SET foreign_key_checks=1;");
|
$db->run("SET foreign_key_checks=1;");
|
||||||
|
|
||||||
echo "\n The database has been cleared\n";
|
echo "\n The database has been cleared\n";
|
||||||
|
unlink("tmp/sanity-lock");
|
||||||
} /**
|
} /**
|
||||||
* @api {php util.php} pop Pop
|
* @api {php util.php} pop Pop
|
||||||
* @apiName pop
|
* @apiName pop
|
||||||
@@ -64,9 +69,14 @@ if ($cmd == 'clean') {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
elseif ($cmd == 'pop') {
|
elseif ($cmd == 'pop') {
|
||||||
|
if (file_exists("tmp/sanity-lock")) {
|
||||||
|
die("Sanity running. Wait for it to finish");
|
||||||
|
}
|
||||||
|
touch("tmp/sanity-lock");
|
||||||
$no = intval($argv[2]);
|
$no = intval($argv[2]);
|
||||||
$block = new Block();
|
$block = new Block();
|
||||||
$block->pop($no);
|
$block->pop($no);
|
||||||
|
unlink("tmp/sanity-lock");
|
||||||
} /**
|
} /**
|
||||||
* @api {php util.php} block-time Block-time
|
* @api {php util.php} block-time Block-time
|
||||||
* @apiName block-time
|
* @apiName block-time
|
||||||
@@ -93,7 +103,7 @@ elseif ($cmd == 'block-time') {
|
|||||||
}
|
}
|
||||||
$time = $t - $x['date'];
|
$time = $t - $x['date'];
|
||||||
$t = $x['date'];
|
$t = $x['date'];
|
||||||
echo "$x[height] -> $time\n";
|
echo "$x[height]\t\t$time\t\t$x[difficulty]\n";
|
||||||
$end = $x['date'];
|
$end = $x['date'];
|
||||||
}
|
}
|
||||||
echo "Average block time: ".ceil(($start - $end) / 100)." seconds\n";
|
echo "Average block time: ".ceil(($start - $end) / 100)." seconds\n";
|
||||||
@@ -183,7 +193,7 @@ elseif ($cmd == "blocks") {
|
|||||||
if ($limit < 1) {
|
if ($limit < 1) {
|
||||||
$limit = 100;
|
$limit = 100;
|
||||||
}
|
}
|
||||||
$r = $db->run("SELECT * FROM blocks WHERE height>:height ORDER by height ASC LIMIT $limit", [":height" => $height]);
|
$r = $db->run("SELECT * FROM blocks WHERE height>:height ORDER by height ASC LIMIT :limit", [":height" => $height, ":limit"=>$limit]);
|
||||||
foreach ($r as $x) {
|
foreach ($r as $x) {
|
||||||
echo "$x[height]\t$x[id]\n";
|
echo "$x[height]\t$x[id]\n";
|
||||||
}
|
}
|
||||||
@@ -443,10 +453,144 @@ elseif ($cmd == 'get-address') {
|
|||||||
* php util.php clean-blacklist
|
* php util.php clean-blacklist
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
} elseif ($cmd == 'clean-blacklist') {
|
} elseif ($cmd == 'clean-blacklist') {
|
||||||
$db->run("UPDATE peers SET blacklisted=0, fails=0, stuckfail=0");
|
$db->run("UPDATE peers SET blacklisted=0, fails=0, stuckfail=0");
|
||||||
echo "All the peers have been removed from the blacklist\n";
|
echo "All the peers have been removed from the blacklist\n";
|
||||||
|
} elseif ($cmd == 'resync-accounts') {
|
||||||
|
// resyncs the balance on all accounts
|
||||||
|
if (file_exists("tmp/sanity-lock")) {
|
||||||
|
die("Sanity running. Wait for it to finish");
|
||||||
|
}
|
||||||
|
touch("tmp/sanity-lock");
|
||||||
|
// lock table to avoid race conditions on blocks
|
||||||
|
$db->exec("LOCK TABLES blocks WRITE, accounts WRITE, transactions WRITE, mempool WRITE");
|
||||||
|
|
||||||
|
$r=$db->run("SELECT * FROM accounts");
|
||||||
|
foreach ($r as $x) {
|
||||||
|
$alias=$x['alias'];
|
||||||
|
if (empty($alias)) {
|
||||||
|
$alias="A";
|
||||||
|
}
|
||||||
|
$rec=$db->single("SELECT SUM(val) FROM transactions WHERE (dst=:id or dst=:alias) AND (height<80000 OR (version!=100 AND version!=103)) and version<111", [":id"=>$x['id'], ":alias"=>$alias]);
|
||||||
|
$spent=$db->single("SELECT SUM(val+fee) FROM transactions WHERE public_key=:pub AND version>0", [":pub"=>$x['public_key']]);
|
||||||
|
if ($spent==false) {
|
||||||
|
$spent=0;
|
||||||
|
}
|
||||||
|
$balance=round(($rec-$spent), 8);
|
||||||
|
if ($x['balance']!=$balance) {
|
||||||
|
echo "rec: $rec, spent: $spent, bal: $x[balance], should be: $balance - $x[id] $x[public_key]\n";
|
||||||
|
if (trim($argv[2])!="check") {
|
||||||
|
$db->run("UPDATE accounts SET balance=:bal WHERE id=:id", [":id"=>$x['id'], ":bal"=>$balance]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$db->exec("UNLOCK TABLES");
|
||||||
|
echo "All done";
|
||||||
|
unlink("tmp/sanity-lock");
|
||||||
|
} elseif ($cmd=="compare-blocks") {
|
||||||
|
$block=new Block();
|
||||||
|
|
||||||
|
$current=$block->current();
|
||||||
|
$peer=trim($argv[2]);
|
||||||
|
$limit=intval($argv[3]);
|
||||||
|
if ($limit==0) {
|
||||||
|
$limit=5000;
|
||||||
|
}
|
||||||
|
for ($i=$current['height']-$limit;$i<=$current['height'];$i++) {
|
||||||
|
$data=peer_post($peer."/peer.php?q=getBlock", ["height" => $i]);
|
||||||
|
if ($data==false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$our=$block->export(false, $i);
|
||||||
|
if ($data!=$our) {
|
||||||
|
echo "Failed block -> $i\n";
|
||||||
|
if ($argv[4]=="dump") {
|
||||||
|
echo "\n\n ---- Internal ----\n\n";
|
||||||
|
var_dump($our);
|
||||||
|
echo "\n\n ---- External ----\n\n";
|
||||||
|
var_dump($data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($cmd=='compare-accounts') {
|
||||||
|
$peer=trim($argv[2]);
|
||||||
|
$r=$db->run("SELECT id,balance FROM accounts");
|
||||||
|
foreach ($r as $x) {
|
||||||
|
$data=peer_post($peer."/api.php?q=getBalance", ["account" => $x['id']]);
|
||||||
|
if ($data==false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($data!=$x['balance']) {
|
||||||
|
echo "$x[id]\t\t$x[balance]\t$data\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif ($cmd=='masternode-hash') {
|
||||||
|
$res=$db->run("SELECT * FROM masternode ORDER by public_key ASC");
|
||||||
|
$block=new Block();
|
||||||
|
$current=$block->current();
|
||||||
|
echo "Height:\t\t$current[height]\n";
|
||||||
|
echo "Hash:\t\t".md5(json_encode($res))."\n\n";
|
||||||
|
} elseif ($cmd=='accounts-hash') {
|
||||||
|
$res=$db->run("SELECT * FROM accounts ORDER by id ASC");
|
||||||
|
$block=new Block();
|
||||||
|
$current=$block->current();
|
||||||
|
echo "Height:\t\t$current[height]\n";
|
||||||
|
echo "Hash:\t\t".md5(json_encode($res))."\n\n";
|
||||||
|
} elseif ($cmd == "version") {
|
||||||
|
echo "\n\n".VERSION."\n\n";
|
||||||
|
} elseif ($cmd == "sendblock"){
|
||||||
|
$peer=trim($argv[3]);
|
||||||
|
if (!filter_var($peer, FILTER_VALIDATE_URL)) {
|
||||||
|
die("Invalid peer hostname");
|
||||||
|
}
|
||||||
|
$peer = filter_var($peer, FILTER_SANITIZE_URL);
|
||||||
|
$height=intval($argv[2]);
|
||||||
|
$block=new Block();
|
||||||
|
$data = $block->export("", $height);
|
||||||
|
|
||||||
|
|
||||||
|
if($data===false){
|
||||||
|
die("Could not find this block");
|
||||||
|
}
|
||||||
|
$response = peer_post($peer."/peer.php?q=submitBlock", $data, 60, true);
|
||||||
|
var_dump($response);
|
||||||
|
|
||||||
|
}elseif ($cmd == "recheck-external-blocks") {
|
||||||
|
$peer=trim($argv[2]);
|
||||||
|
if (!filter_var($peer, FILTER_VALIDATE_URL)) {
|
||||||
|
die("Invalid peer hostname");
|
||||||
|
}
|
||||||
|
$peer = filter_var($peer, FILTER_SANITIZE_URL);
|
||||||
|
|
||||||
|
|
||||||
|
$blocks = [];
|
||||||
|
$block = new Block();
|
||||||
|
$height=intval($argv[3]);
|
||||||
|
|
||||||
|
$last=peer_post($peer."/peer.php?q=currentBlock");
|
||||||
|
|
||||||
|
$b=peer_post($peer."/peer.php?q=getBlock",["height"=>$height]);
|
||||||
|
|
||||||
|
for ($i = $height+1; $i <= $last['height']; $i++) {
|
||||||
|
$c=peer_post($peer."/peer.php?q=getBlock",["height"=>$i]);
|
||||||
|
|
||||||
|
if (!$block->mine(
|
||||||
|
$c['public_key'],
|
||||||
|
$c['nonce'],
|
||||||
|
$c['argon'],
|
||||||
|
$c['difficulty'],
|
||||||
|
$b['id'],
|
||||||
|
$b['height'],
|
||||||
|
$c['date']
|
||||||
|
)) {
|
||||||
|
print("Invalid block detected. $c[height] - $c[id]\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
echo "Block $i -> ok\n";
|
||||||
|
$b=$c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
echo "Invalid command\n";
|
echo "Invalid command\n";
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user