mirror of
https://github.com/kvazar-network/crawler.git
synced 2025-01-22 04:45:18 +00:00
implement transaction parser
This commit is contained in:
parent
ee221bb535
commit
ea5c775df3
2
.gitignore
vendored
2
.gitignore
vendored
@ -2,4 +2,4 @@
|
|||||||
|
|
||||||
/composer.lock
|
/composer.lock
|
||||||
/config.json
|
/config.json
|
||||||
/.block
|
/.state
|
@ -10,4 +10,5 @@
|
|||||||
* `cd crawler`
|
* `cd crawler`
|
||||||
* `cp example/config.json config.json`
|
* `cp example/config.json config.json`
|
||||||
* `crontab -e`:`* * * * * php kvazar/crawler/src/index.php`
|
* `crontab -e`:`* * * * * php kvazar/crawler/src/index.php`
|
||||||
* drop index: `php kvazar/crawler/src/index.php drop`
|
* drop index: `php kvazar/crawler/src/index.php drop`
|
||||||
|
* optimize index: `php kvazar/crawler/src/index.php optimize`
|
286
src/index.php
286
src/index.php
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
// Prevent multi-thread execution
|
// Prevent multi-thread execution
|
||||||
$semaphore = sem_get(
|
$semaphore = sem_get(
|
||||||
crc32(__DIR__), 1
|
crc32(__FILE__), 1
|
||||||
);
|
);
|
||||||
|
|
||||||
if (false === sem_acquire($semaphore, true))
|
if (false === sem_acquire($semaphore, true))
|
||||||
@ -26,21 +26,21 @@ $config = json_decode(
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Init block
|
// Init current block state
|
||||||
$block = 0;
|
$state = 1;
|
||||||
|
|
||||||
if (file_exists(__DIR__ . '/../.block'))
|
if (file_exists(__DIR__ . '/../.state'))
|
||||||
{
|
{
|
||||||
$block = (int) file_get_contents(
|
$state = (int) file_get_contents(
|
||||||
__DIR__ . '/../.block'
|
__DIR__ . '/../.state'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
file_put_contents(
|
file_put_contents(
|
||||||
__DIR__ . '/../.block',
|
__DIR__ . '/../.state',
|
||||||
$block
|
$state
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,11 +115,27 @@ if (isset($argv[1]))
|
|||||||
true
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
file_put_contents(
|
||||||
|
__DIR__ . '/../.state',
|
||||||
|
1
|
||||||
|
);
|
||||||
|
|
||||||
exit(
|
exit(
|
||||||
_('Index dropped!')
|
_('Index dropped!')
|
||||||
);
|
);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Index optimization request
|
||||||
|
case 'optimize':
|
||||||
|
|
||||||
|
$index->optimize();
|
||||||
|
|
||||||
|
exit(
|
||||||
|
_('Index optimized!')
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,16 +147,262 @@ if (false === $blocks = $kevacoin->getBlockCount())
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for ($i = $block; $i <= $blocks; $i++)
|
for ($block = $state; $block <= $blocks; $block++)
|
||||||
{
|
{
|
||||||
|
// Debug progress
|
||||||
echo sprintf(
|
echo sprintf(
|
||||||
"%d/%d\r",
|
"%d/%d\r",
|
||||||
$i,
|
$block,
|
||||||
$blocks
|
$blocks
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Get block hash
|
||||||
|
if (!$hash = $kevacoin->getBlockHash($block))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive "%d" block hash!'),
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get block data
|
||||||
|
if (!$data = $kevacoin->getBlock($hash))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive "%d" block data by hash "%s"!'),
|
||||||
|
$block,
|
||||||
|
$hash
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($data['tx']))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive tx data in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process each transaction in block
|
||||||
|
foreach ((array) $data['tx'] as $transaction)
|
||||||
|
{
|
||||||
|
// Validate each transaction
|
||||||
|
if (!$raw = $kevacoin->getRawTransaction($transaction))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive raw transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($raw['txid']))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive txid of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($raw['vout']))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive vout of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($raw['time']))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive time of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($raw['size']))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Could not receive size of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse transaction data
|
||||||
|
foreach((array) $raw['vout'] as $vout) {
|
||||||
|
|
||||||
|
if (!$vout || empty($vout['scriptPubKey']) || empty($vout['scriptPubKey']['asm']))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Invalid vout transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse space-separated fragments to array
|
||||||
|
$asm = explode(
|
||||||
|
' ',
|
||||||
|
$vout['scriptPubKey']['asm']
|
||||||
|
);
|
||||||
|
|
||||||
|
// Get operation ID required to continue
|
||||||
|
if (empty($asm[0]))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Undefined operation of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect key / value
|
||||||
|
switch ($asm[0]) {
|
||||||
|
|
||||||
|
case 'OP_KEVA_PUT':
|
||||||
|
|
||||||
|
if (empty($asm[1]) || empty($asm[2]) || empty($asm[3]))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Undefined namespace or key or value of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$namespace = \Kvazar\Crypto\Base58::encode(
|
||||||
|
$asm[1], false, 0, false
|
||||||
|
);
|
||||||
|
|
||||||
|
$key = \Kvazar\Crypto\Kevacoin::decode(
|
||||||
|
$asm[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
$value = \Kvazar\Crypto\Kevacoin::decode(
|
||||||
|
$asm[3]
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'OP_KEVA_DELETE':
|
||||||
|
|
||||||
|
if (empty($asm[1]) || empty($asm[2]))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Undefined namespace or key of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$namespace = \Kvazar\Crypto\Base58::encode(
|
||||||
|
$asm[1], false, 0, false
|
||||||
|
);
|
||||||
|
|
||||||
|
$key = \Kvazar\Crypto\Kevacoin::decode(
|
||||||
|
$asm[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
$value = '';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'OP_KEVA_NAMESPACE':
|
||||||
|
|
||||||
|
if (empty($asm[1]) || empty($asm[2]))
|
||||||
|
{
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Undefined namespace or value of transaction "%s" in block "%d"!'),
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$namespace = \Kvazar\Crypto\Base58::encode(
|
||||||
|
$asm[1], false, 0, false
|
||||||
|
);
|
||||||
|
|
||||||
|
$key = '_KEVA_NS_';
|
||||||
|
|
||||||
|
$value = \Kvazar\Crypto\Kevacoin::decode(
|
||||||
|
$asm[2]
|
||||||
|
);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'OP_HASH160': // @TODO not in use at this moment
|
||||||
|
|
||||||
|
/*
|
||||||
|
[0] => OP_HASH160
|
||||||
|
[1] => d03b0c06f8db322a2365e41385f2c8f6f89eebe3
|
||||||
|
[2] => OP_EQUAL
|
||||||
|
*/
|
||||||
|
|
||||||
|
continue 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'OP_RETURN': // @TODO not in use at this moment
|
||||||
|
|
||||||
|
/*
|
||||||
|
[0] => OP_RETURN
|
||||||
|
[1] => aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf9
|
||||||
|
*/
|
||||||
|
|
||||||
|
continue 2;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
exit(
|
||||||
|
sprintf(
|
||||||
|
_('Undefined operation "%s" of transaction "%s" in block "%d"!'),
|
||||||
|
$asm[0],
|
||||||
|
$transaction,
|
||||||
|
$block
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add index record @TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update current block indexed
|
||||||
file_put_contents(
|
file_put_contents(
|
||||||
__DIR__ . '/../.block',
|
__DIR__ . '/../.state',
|
||||||
$i
|
$block
|
||||||
);
|
);
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user