Skip to content

Instantly share code, notes, and snippets.

@nishimura
Last active January 9, 2018 11:52
Show Gist options
  • Save nishimura/3fd6af566bb4372a7c7a26dfbf91d69f to your computer and use it in GitHub Desktop.
Save nishimura/3fd6af566bb4372a7c7a26dfbf91d69f to your computer and use it in GitHub Desktop.
Search Block Index by PHP5
<?php
// needs: PHP5, db4.so
// from oracle web site
//
// php db4blkindex.php <XP_data_directory> [<block hash suffix>]
error_reporting(-1);
$dbenv = new Db4Env();
$ret = $dbenv->open($argv[1],
DB_CREATE |
DB_INIT_CDB |
DB_INIT_MPOOL,
0444);
if ($ret === false){
die('dbenv open error');
}
$db = new Db4($dbenv);
$ret = $db->open(null, 'blkindex.dat', 'main');
$cursor = $db->cursor();
function reverse16($str){
return implode('', array_reverse(str_split($str, 2)));
}
class uint256
{
private $uint32s;
public function __construct($uint32s)
{
$this->uint32s = $uint32s;
}
public function __toString()
{
$ret = '';
$len = count($this->uint32s);
for ($i = 1; $i < $len; $i++){
$ret .= sprintf('%08x', $this->uint32s['i'.$i]);
}
return reverse16($ret);;
}
}
// $txkey = bin2hex("\x02tx");
// echo "$txkey\n";
// $blockkey = bin2hex("\nblockindex");
// echo "blockkey: $blockkey\n";
//
// $range = pack("N", 0x02780000);
// $range = pack("NNN", 0x0a626c6f, 0x636b696e, 0x00);
//
// echo "range: $range\n";
// echo printf("08x: %08x\n", unpack('Ni1', $range)['i1']);
// echo "strlen:" . strlen($range) . "\n";
$i = 0;
function strPack($str, $block = null){
$len = strlen($str);
$chars = [];
$prefix = '';
for ($i = 0; $i < $len; $i++){
$prefix .= sprintf('%02x', ord($str[$i]));
}
$len = strlen($prefix);
$int8s = str_split($prefix, 2);
$int32s = [];
$blocklen = 0;
if ($block !== null){
$block = str16Pack($block);
$blocklen = strlen($block);
$pad = $blocklen % 8;
$block = str_pad($block, $blocklen + (8 - $pad) % 8, '0');
$int32s = str_split($block, 8);
}
$retlen = $len + $blocklen;
$len8 = count($int8s);
$len32 = count($int32s);
foreach ($int8s as $k => $v)
$int8s[$k] = intval($v, 16);
foreach ($int32s as $k => $v)
$int32s[$k] = intval($v, 16);
return [$retlen / 2,
pack(str_repeat('C', $len8) . str_repeat('N', $len32),
...$int8s, ...$int32s)];
}
function str16Pack($str){
$len = strlen($str);
$pad = $len % 2;
$str = str_pad($str, $len + $pad, '0', STR_PAD_LEFT);
$ret = reverse16($str);
return $ret;
}
function startsWith($haystack, $needle){
return (strpos($haystack, $needle) === 0);
}
$prefix = "\nblockindex";
$block = null;
if (isset($argv[2]))
$block = $argv[2];
list($len, $prefix) = strPack($prefix, $block);
// var_dump(['len' => $len, $prefix]);
// $unpack = unpack('C/ni0/N/N/Ni1/Ni2', $prefix);
// var_dump(sprintf("08x: %08x %08x %08x\n",
// $unpack['i0'], $unpack['i1'], $unpack['i2']));
// var_dump(['uint256' => new uint256(str16Pack($argv[2])) . '']);
$key = $prefix;
//$key = pack("NNN", 0x0a626c6f, 0x636b696e, 0x64657800);
$value = 0;
$ret = $cursor->get($key, $value, DB_SET_RANGE);
$prefix = substr($prefix, 0, $len);
while ($ret == 0){
if (!startsWith($key, $prefix)){
break;
}
//printf("%d, %d\n", strlen($key), strlen($value));
//printf("%s, %s\n", $key, $value);
// uint256: N(32) * 8
// \0x0a blockindex [4 * 8 = 32byte]
$uint32s = unpack('n/C/N/N/Ni1/Ni2/Ni3/Ni4/Ni5/Ni6/Ni7/Ni8', $key);
$uint256 = new uint256($uint32s);
$i++;
if ($i % 10000 === 0){
echo "$i.";
}
$ret = $cursor->get($key, $value, DB_NEXT);
// test
echo $uint256 . "\n";
if ($i > 3) break;
}
var_dump(['count' => $i]);
$cursor->close();
$db->close();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment