Browse Source

implement transaction parser

main
ghost 8 months ago
parent
commit
ea5c775df3
  1. 2
      .gitignore
  2. 1
      README.md
  3. 286
      src/index.php

2
.gitignore vendored

@ -2,4 +2,4 @@
/composer.lock /composer.lock
/config.json /config.json
/.block /.state

1
README.md

@ -11,3 +11,4 @@
* `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

@ -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…
Cancel
Save