Difficulty

7 messages BitcoinTalk mizerydearia, Insti, Satoshi Nakamoto, ArtForz July 27, 2010 — August 4, 2010
mizerydearia July 27, 2010 10:11 UTC Source ·

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>
Insti July 27, 2010 15:45 UTC Source ·

I’m just thankful the difficulty isn’t 244.213223092375323881335701184896212407930361873708113773326734402748260502489 1554339282075169582811726687822061777635447902413461818393548574922122914786456 6654051064077556842993973623686279076537890477160907158869253835628402573582928 17840402922938076799907

Just imagine how hard it would be to win a block then!!!!!

mizerydearia July 28, 2010 00:31 UTC Source ·

Actually, calculating with another digit comes out to 244.213223092375323881335701184896212407930361873708113773326734402748260502489 1554339282075169582811726687822061777635447902413461818393548574922122914786456 6654051064077556842993973623686279076537890477160907158869253835628402573582928 178404029229380767999068 and thus could be rounded up to the value you suggested Insti.

Satoshi Nakamoto July 29, 2010 01:16 UTC Source ·

You were looking at the wrong code.  Here’s the code that applies:

bool CBlock::CheckBlock() const
{
...
    // Check timestamp
    if (nTime > GetAdjustedTime() + 2 * 60 * 60)
        return error("CheckBlock() : block timestamp too far in the future");
...

bool CBlock::AcceptBlock()
{
   ...
    // Check timestamp against prev
    if (nTime <= pindexPrev->GetMedianTimePast())
        return error("AcceptBlock() : block's timestamp is too early");

The timestamp is limited to up to 2 hours in the future.  It can be earlier than the previous block, but it must be greater than the median of the last 11 blocks.  The reason for doing it that way is so the time can get corrected in the next block if the previous block had the time too far in the future, like what happened.

mizerydearia August 4, 2010 09:06 UTC Source ·

If C++ SetCompact(unsigned int nCompact) function is

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;
}
With Python equivalent of
def uint256_from_compact(c):
	nbytes = (c >> 24) & 0xFF
	v = (c & 0xFFFFFFL) << (8 * (nbytes - 3))
	return v
And PHP equvalent of
function uint256_from_compact($c) {
	$nbytes = ($c >> 24) & 0xFF;
	return bcmul($c & 0xFFFFFF,bcpow(2,8 * ($nbytes - 3)));
}

then for C++ Getcompact() function

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;
}

how can I produce simplistic code for python/php to produce equivalent function?

My intention is to use the function in this php snippet

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;
}
ArtForz August 4, 2010 14:21 UTC Source ·

this is my quick and dirty reference implementation for python, tested against bitcoins implementation for -256…256 and with about 4000 random numbers varying in size from 8-256 bits. Writing a faster and more pythonic version should be pretty easy, but I can’t be arsed right now…

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)
mizerydearia August 4, 2010 14:45 UTC Source ·

Thanks ArtForz! ^_^

Quote from: ArtForz on August 04, 2010, 2:21:22 PM 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
I confirmed again that both of these produce same output when using 0x1d00ffff