在PHP(比特币)中读取一个8字节整数


Reading an 8 byte integer in PHP (Bitcoin)

我正在尝试从比特币交易中读取值-https://en.bitcoin.it/wiki/Transaction

维基说它是一个8字节的整数,但我尝试过的解包都没有给我一个正确的十进制值。

除了输出中的值之外,我已经能够从事务中读取其他所有内容——考虑到我已经解析的其他字段,所有字段都符合正确的值——我读取的是正确的8个字节。

带有:

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

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

应该是500和0.0691375。

正如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"