/**
  * @param BlockHeaderInterface $header
  * @return bool
  * @throws \Exception
  */
 public function checkHeader(BlockHeaderInterface $header)
 {
     $math = $this->math;
     $target = $this->difficulty->getTarget($header->getBits());
     if ($math->cmp($target, 0) == 0 || $math->cmp($target, $this->limit()) > 0) {
         throw new \Exception('nBits below minimum work');
     }
     $hashInt = $math->hexDec($header->getBlockHash());
     if ($math->cmp($hashInt, $target) > 0) {
         throw new \Exception("Hash doesn't match nBits");
     }
     return true;
 }
 /**
  * Given an ancestor height, and a list of hashes in the fork, use this
  * information to compare the work, and if necessary, commit a reorg.
  *
  * @param int $ancestorHeight
  * @param array $forkBlockHashes
  * @return bool
  * @throws \Exception
  */
 public function processFork($ancestorHeight, array $forkBlockHashes)
 {
     $blocks = $this->blocks();
     $index = $this->index();
     /** @var \BitWasp\Bitcoin\Block\BlockHeaderInterface[] $chainHeaders */
     $chainHeaders = [];
     $chainHeight = $index->height()->height();
     for ($i = $ancestorHeight; $i < $chainHeight; $i++) {
         $chainHeaders[] = $blocks->fetch($index->hash()->fetch($i))->getHeader();
     }
     /** @var \BitWasp\Bitcoin\Block\BlockHeaderInterface[] $forkBlocks */
     $forkBlocks = [];
     $forkHeaders = [];
     foreach ($forkBlockHashes as $hash) {
         $block = $blocks->fetch($hash);
         $forkBlocks[] = $block;
         $forkHeaders[] = $block->getHeader();
     }
     // Only recalculate BlockIndex values if fork has greater work than chain blocks since ancestor
     if ($this->difficulty->compareWork($forkHeaders, $chainHeaders) > 0) {
         $index->reorg($ancestorHeight, $forkHeaders);
         return true;
     }
     return false;
 }
Exemple #3
0
 /**
  * @param TransactionInterface|null $coinbaseTx
  * @return Block
  * @throws \BitWasp\Bitcoin\Exceptions\MerkleTreeEmpty
  */
 public function run(TransactionInterface $coinbaseTx = null)
 {
     $nonce = '0';
     $maxNonce = $this->math->pow(2, 32);
     // Allow user supplied transactions
     if ($coinbaseTx == null) {
         $coinbaseTx = new Transaction();
         $coinbaseTx->getInputs()->addInput(new TransactionInput('0000000000000000000000000000000000000000000000000000000000000000', 4294967295.0));
         $coinbaseTx->getOutputs()->addOutput(new TransactionOutput(5000000000.0, $this->script));
     }
     $inputs = $coinbaseTx->getInputs();
     $found = false;
     $usingDiff = $this->lastBlockHeader->getBits();
     $diff = new Difficulty($this->math);
     $target = $diff->getTarget($usingDiff);
     while (false === $found) {
         // Set coinbase script, and build Merkle tree & block header.
         $inputs->getInput(0)->setScript($this->getCoinbaseScriptBuf());
         $transactions = new TransactionCollection(array_merge(array($coinbaseTx), $this->transactions->getTransactions()));
         $merkleRoot = new MerkleRoot($this->math, $transactions);
         $merkleHash = $merkleRoot->calculateHash();
         $header = new BlockHeader($this->version, $this->lastBlockHeader->getBlockHash(), $merkleHash, $this->timestamp, $usingDiff, '0');
         $t = microtime(true);
         // Loop through all nonces (up to 2^32). Restart after modifying extranonce.
         while ($this->math->cmp($header->getNonce(), $maxNonce) <= 0) {
             $header->setNonce($this->math->add($header->getNonce(), '1'));
             $hash = (new Parser())->writeBytes(32, Hash::sha256d($header->getBuffer()), true)->getBuffer();
             if ($this->math->cmp($hash->getInt(), $target) <= 0) {
                 $block = new Block($this->math, $header, $transactions);
                 return $block;
             }
             if ($this->report && $this->math->cmp($this->math->mod($header->getNonce(), 100000), '0') == 0) {
                 $time = microtime(true) - $t;
                 $khash = $nonce / $time / 1000;
                 echo "extraNonce[{$this->extraNonce}] nonce[{$nonce}] time[{$time}] khash/s[{$khash}] \n";
             }
         }
         // Whenever we exceed 2^32, increment extraNonce and reset $nonce
         $this->extraNonce++;
         $nonce = '0';
     }
 }
<?php 
require_once __DIR__ . "/../vendor/autoload.php";
use BitWasp\Bitcoin\Address\AddressFactory;
use BitWasp\Bitcoin\Rpc\RpcFactory;
use BitWasp\Bitcoin\Chain\Difficulty;
use BitWasp\Bitcoin\Math\Math;
use BitWasp\Bitcoin\Network\NetworkFactory;
use BitWasp\Bitcoin\Bitcoin;
use BitWasp\Bitcoin\Script\OutputScriptFactory;
use BitWasp\Bitcoin\Script\ScriptFactory;
use BitWasp\Buffertools\Buffer;
use willgriffin\MariaInterface\MariaInterface;
$configFile = count($argv) > 1 ? $argv[1] : false;
$x = count($argv) > 2 ? intval($argv[2]) : 1;
$math = new Math();
$difficulty = new Difficulty($math);
if (file_exists($configFile)) {
    $config = (object) parse_ini_file($configFile);
    //$currency = Main::getCurrency($currencyName);
    $db = new MariaInterface(["host" => $config->dbhost, "user" => $config->dbuser, "pass" => $config->dbpass, "port" => $config->dbport, "name" => $config->dbname]);
    $bitcoind = RpcFactory::bitcoind($config->rpchost, $config->rpcport, $config->rpcuser, $config->rpcpass);
    $network = NetworkFactory::create($config->magic_byte, $config->magic_p2sh_byte, $config->private_key_byte)->setHDPubByte($config->hd_pub_byte)->setHDPrivByte($config->hd_priv_byte)->setNetMagicBytes($config->net_magic_bytes);
    Bitcoin::setNetwork($network);
    $nextBlockHash = $bitcoind->getblockhash($x);
    do {
        echo "Block {$x}\n";
        $blockhash = $nextBlockHash;
        $block = $bitcoind->getblock($blockhash);
        $blockHeader = $block->getHeader();
        $blockBits = $blockHeader->getBits();
        $blockTime = $blockHeader->getTimestamp();