public function testCreateInstance() { $ecAdapter = Bitcoin::getEcAdapter(); $params = new Params($ecAdapter->getMath()); $consensus = new Consensus($ecAdapter->getMath(), $params); $proofOfWork = new ProofOfWork($ecAdapter->getMath(), $params); $check = new HeaderCheck($consensus, $ecAdapter, $proofOfWork); $header = BlockHeaderFactory::fromHex($this->getGenesisHex()); $hash = $header->getHash(); $this->assertNoException(function () use($check, $hash, $header) { $check->check($hash, $header, false); }); $this->assertNoException(function () use($check, $hash, $header) { $check->check($hash, $header, true); }); $badHeader = new BlockHeader($header->getVersion(), $header->getPrevBlock(), $header->getMerkleRoot(), $header->getTimestamp(), $header->getBits(), 1); $this->assertException(function () use($check, $badHeader) { $hash = $badHeader->getHash(); $check->check($hash, $badHeader, true); }); }
/** * @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'; } }
/** * @param string $blockhash * @return \BitWasp\Bitcoin\Block\Block */ public function getblock($blockhash) { $blockArray = $this->client->execute('getblock', [$blockhash, true]); $this->checkNotNull($blockArray); // Establish batch query for loading transactions $txs = []; if (count($blockArray['tx']) > 0) { $this->client->batch(); foreach ($blockArray['tx'] as $txid) { $this->client->execute('getrawtransaction', array($txid)); } $result = $this->client->send(); // Build the transactions $txs = array_map(function ($value) { return TransactionFactory::fromHex($value); }, $result); } // Build block header $header = new BlockHeader($blockArray['version'], @$blockArray['previousblockhash'], $blockArray['merkleroot'], $blockArray['time'], Buffer::hex($blockArray['bits']), $blockArray['nonce']); if (isset($blockArray['nextblockhash'])) { $header->setNextBlock($blockArray['nextblockhash']); } return new Block(Bitcoin::getMath(), $header, new TransactionCollection($txs)); }