難易度
http://nullvoid.org/bitcoin/difficultiez.php
<?
header("Content-type: text/html");
require_once 'jsonRPCClient.php';
$data=new jsonRPCClient('http://127.0.0.1:8332');
$blockcount = $data->getblockcount();
$now = date("U");
$blockfile = "blockdata";
$data = file($blockfile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); array_pop($data);
?><html>
<head>
<meta http-equiv="refresh" content="100000">
</head>
<body>
<pre>
<?
function humantime($secs) {
if ($secs<0) return false;
$m = (int)($secs / 60); $s = $secs % 60; $s = ($s <= 9) ? "0$s" : $s;
$h = (int)($m / 60); $m = $m % 60; $m = ($m <= 9) ? "0$m" : $m;
$d = (int)($h / 24); $h = $h % 24; $h = ($h <= 9) ? "0$h" : $h;
$d = ($d <= 9) ? "0$d" : $d;
return $d."d $h:$m:$s";
}
// Converted from ArtForz's python code http://bitcointalk.org/index.php?topic=464.msg4080#msg4080
function uint256_from_compact($c) {
$nbytes = ($c >> 24) & 0xFF;
return bcmul($c & 0xFFFFFF,bcpow(2,8 * ($nbytes - 3)));
}
$tblock = 0;
$nTargetTimespan = 60 * 60 * 24 * 14;
bcscale(256);
foreach ($data as $line) {
$blocks = strtok($line, " ");
$date = strtok(" ");
$avghash = strtok(" ");
$bits = strtok(" ");
if ($blocks == 0 || $blocks == $tblock) {
$tblock = $blocks + 2016;
$blocknum = str_repeat(" ", 6 - strlen($blocks)).$blocks;
echo "Block $blocknum was generated at $date (".date("r", $date).")";
if ($blocks != 0) {
$intervalnum = $date - $lastdate;
$interval = str_repeat(" ", 9 - strlen($intervalnum)).$intervalnum;
echo " $interval seconds interval (".humantime($intervalnum).")";
echo " Difficulty: ".bcdiv(bcdiv(bcmul(uint256_from_compact(0x1D00FFFF),1000), uint256_from_compact($bits)), 1000);
$lastdate = $date;
}
echo "<br>";
}
}
?>
</pre>
</body>
</html> 難易度が 244.213223092375323881335701184896212407930361873708113773326734402748260502489 1554339282075169582811726687822061777635447902413461818393548574922122914786456 6654051064077556842993973623686279076537890477160907158869253835628402573582928 17840402922938076799907 じゃなくて本当に良かった
その場合、ブロックを獲得するのがどれだけ大変か想像してみてくれ!!!!!
実際、もう 1 桁追加して計算すると 244.213223092375323881335701184896212407930361873708113773326734402748260502489 1554339282075169582811726687822061777635447902413461818393548574922122914786456 6654051064077556842993973623686279076537890477160907158869253835628402573582928 178404029229380767999068 となり、Insti が示した値に切り上げられる。
見ていたコードが間違っている。適用されるコードはこちらだ:
bool CBlock::CheckBlock() const
{
...
// タイムスタンプをチェック
if (nTime > GetAdjustedTime() + 2 * 60 * 60)
return error("CheckBlock() : block timestamp too far in the future");
...
bool CBlock::AcceptBlock()
{
...
// 前のブロックに対してタイムスタンプをチェック
if (nTime <= pindexPrev->GetMedianTimePast())
return error("AcceptBlock() : block's timestamp is too early");
タイムスタンプは未来方向には最大 2時間に制限されている。前のブロックより早い時刻にすることはできるが、直近 11 ブロックの中央値より大きくなければならない。このようにしている理由は、前のブロックのタイムスタンプが未来すぎた場合(今回起きたように)、次のブロックで時刻を修正できるようにするためだ。
C++の SetCompact(unsigned int nCompact)関数が以下のようだとして、
CBigNum& SetCompact(unsigned int nCompact) {
unsigned int nSize = nCompact >> 24;
std::vector<unsigned char> vch(4 + nSize);
vch[3] = nSize;
if (nSize >= 1) vch[4] = (nCompact >> 16) & 0xff;
if (nSize >= 2) vch[5] = (nCompact >> 8) & 0xff;
if (nSize >= 3) vch[6] = (nCompact >> 0) & 0xff;
BN_mpi2bn(&vch[0], vch.size(), this);
return *this;
}
これに対応するPythonが
def uint256_from_compact(c):
nbytes = (c >> 24) & 0xFF
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
return v
対応するPHPが
function uint256_from_compact($c) {
$nbytes = ($c >> 24) & 0xFF;
return bcmul($c & 0xFFFFFF,bcpow(2,8 * ($nbytes - 3)));
}
そして、C++の Getcompact()関数
unsigned int GetCompact() const {
unsigned int nSize = BN_bn2mpi(this, NULL);
std::vector<unsigned char> vch(nSize);
nSize -= 4;
BN_bn2mpi(this, &vch[0]);
unsigned int nCompact = nSize << 24;
if (nSize >= 1) nCompact |= (vch[4] << 16);
if (nSize >= 2) nCompact |= (vch[5] << 8);
if (nSize >= 3) nCompact |= (vch[6] << 0);
return nCompact;
}
であるとき、C++の Getcompact()関数に対応する Python/PHP の単純なコードはどう書けばいい?
この php スニペットの中で関数を使うつもりだ
function GetNextWorkRequired($block, $bits, $nActualTimespan) {
$nTargetTimespan = 60 * 60 * 24 * 14; // 2 weeks
if ($nActualTimespan < $nTargetTimespan / 4) { $nActualTimespan = $nTargetTimespan / 4; }
if ($nActualTimespan > $nTargetTimespan * 4) { $nActualTimespan = $nTargetTimespan * 4; }
$bits = uint256_from_compact($bits);
$bits = bcmul($bits,$nActualTimespan);
$bits = bcdiv($bits,$nTargetTimespan);
$bits = uint256_to_compact($bits); // <-- Need to translate C++ code for GetCompact()
return $bits;
} これが Python 向けの俺の手早く雑な参照実装だ。-256〜256 の範囲と、8〜256 ビットでサイズの異なるランダムな数値約 4000個について、Bitcoin の実装と照らし合わせてテスト済みだ。 もっと速く Python らしいバージョンを書くのは簡単なはずだが、今はその気になれない…
import struct
def mpi2num(m):
"""convert MPI string to number"""
datasize = struct.unpack(">I", m[0:4])[0]
r = 0
if datasize:
neg_flag = bool(ord(m[4]) & 0x80)
r = ord(m[4]) & 0x7F
for i in xrange(1, datasize):
r <<= 8
r += ord(m[4+i])
if neg_flag:
r = -r
return r
def num2mpi(n):
"""convert number to MPI string"""
if n == 0:
return struct.pack(">I", 0)
r = ""
neg_flag = bool(n < 0)
n = abs(n)
while n:
r = chr(n & 0xFF) + r
n >>= 8
if ord(r[0]) & 0x80:
r = chr(0) + r
if neg_flag:
r = chr(ord(r[0]) | 0x80) + r[1:]
datasize = len(r)
return struct.pack(">I", datasize) + r
def GetCompact(n):
"""convert number to bc compact uint"""
mpi = num2mpi(n)
nSize = len(mpi) - 4
nCompact = (nSize & 0xFF) << 24
if nSize >= 1:
nCompact |= (ord(mpi[4]) << 16)
if nSize >= 2:
nCompact |= (ord(mpi[5]) << 8)
if nSize >= 3:
nCompact |= (ord(mpi[6]) << 0)
return nCompact
def SetCompact(nCompact):
"""convert bc compact uint to number"""
nSize = (nCompact >> 24) & 0xFF
tbuf = "\x00\x00\x00" + chr(nSize)
if nSize >= 1:
tbuf += chr((nCompact >> 16) & 0xFF)
if nSize >= 2:
tbuf += chr((nCompact >> 8) & 0xFF)
if nSize >= 3:
tbuf += chr((nCompact >> 0) & 0xFF)
tbuf += "\x00" * (nSize - 3)
return mpi2num(tbuf) ArtForz ありがとう! ^_^
ArtForzの投稿(2010年8月4日 14:21 UTC)Code:import struct
def SetCompact(nCompact): """convert bc compact uint to number""" nSize = (nCompact >> 24) & 0xFF tbuf = “\x00\x00\x00” + chr(nSize) if nSize >= 1: tbuf += chr((nCompact >> 16) & 0xFF) if nSize >= 2: tbuf += chr((nCompact >> 8) & 0xFF) if nSize >= 3: tbuf += chr((nCompact >> 0) & 0xFF) tbuf += “\x00” * (nSize - 3) return mpi2num(tbuf)
def uint256_from_compact(c):
nbytes = (c >> 24) & 0xFF
v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
return v
これら両方が0x1d00ffffを使ったとき同じ出力を生成することを改めて確認した