Чтение 8-байтового целого числа в PHP (биткойн)


Я пытаюсь прочитать значение транзакции биткойна - https://en.bitcoin.it/wiki/Transaction

В вики говорится, что это 8-байтовое целое число, но ничто из того, что я пробовал с помощью unpack, не дает мне правильного десятичного значения.

Я смог прочитать все остальное из транзакции, кроме значений на выходе - учитывая другие поля, мне удалось проанализировать все строки с правильными значениями, похоже, я читаю правильные 8 байт.

С помощью:

$bin = hex2bin('00743ba40b000000');
$value = unpack('lvalue', $bin);
// 'value' => int -1539607552

И

$bin = hex2bin('d67e690000000000');
$value = unpack('lvalue', $bin);
// 'value' => int 6913750

Это должно быть 500 и 0,0691375.

Author: Darren S, 2013-07-17

1 answers

В качестве документации для PHP unpack() примечания к функциям, могут произойти странные вещи, если вы попытаетесь распаковать значение без знака длиной, равной собственному целочисленному размеру PHP (т.е. 32 или 64 бита в зависимости от того, как был скомпилирован ваш PHP):

"Обратите внимание, что PHP внутренне хранит целочисленные значения как подписанные. Если вы распакуете большую длину без знака, и она имеет тот же размер, что и значения, хранящиеся внутри PHP, результатом будет отрицательное число, даже если распаковка без знака была указано".

Возможно, это ошибка PHP: если я попрошу значение без знака, я, черт возьми, ожидаю, что получу значение без знака, даже если оно должно быть внутренне представлено в виде поплавка.

В любом случае, один из способов обойти эту "причуду" - распаковать двоичную строку на меньшие куски, скажем, по 8 или 16 бит каждый, и собрать их вручную, вот так:

$bin = pack( 'H*', '00743ba40b000000' );

$words = array_reverse( unpack( 'v*', $bin ) );
$n = 0;
foreach ( $words as $word ) {
    $n = (1 << 16) * $n + $word;
}

echo "$n\n";  // prints "50000000000"
 1
Author: Ilmari Karonen, 2013-07-17 20:39:51