/** * @param BlockInterface $block * @param BlockData $blockData * @param bool $checkSignatures * @param bool $flags * @param $height */ public function checkBlockData(BlockInterface $block, BlockData $blockData, $checkSignatures, $flags, $height) { $validation = new ScriptValidation($checkSignatures, $flags); foreach ($block->getTransactions() as $tx) { $blockData->nSigOps += $this->blockCheck->getLegacySigOps($tx); if ($blockData->nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) { throw new \RuntimeException('Blocks::accept() - too many sigops'); } if (!$tx->isCoinbase()) { if ($flags & InterpreterInterface::VERIFY_P2SH) { $blockData->nSigOps += $this->blockCheck->getP2shSigOps($blockData->utxoView, $tx); if ($blockData->nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) { throw new \RuntimeException('Blocks::accept() - too many sigops'); } } $blockData->nFees = $this->math->add($blockData->nFees, $blockData->utxoView->getFeePaid($this->math, $tx)); $this->blockCheck->checkInputs($blockData->utxoView, $tx, $height, $flags, $validation); } } if ($validation->active() && !$validation->result()) { throw new \RuntimeException('ScriptValidation failed!'); } $this->blockCheck->checkCoinbaseSubsidy($block->getTransaction(0), $blockData->nFees, $height); }
/** * @param BlockInterface $block * @param TransactionSerializerInterface $txSerializer * @return Buffer * @throws MerkleTreeEmpty */ public function calcMerkleRoot(BlockInterface $block, TransactionSerializerInterface $txSerializer) { $hashFxn = function ($value) { return hash('sha256', hash('sha256', $value, true), true); }; $txCount = count($block->getTransactions()); if ($txCount === 0) { // TODO: Probably necessary. Should always have a coinbase at least. throw new MerkleTreeEmpty('Cannot compute Merkle root of an empty tree'); } if ($txCount === 1) { $transaction = $block->getTransaction(0); $serialized = $txSerializer->serialize($transaction); $binary = $hashFxn($serialized->getBinary()); } else { // Create a fixed size Merkle Tree $tree = new FixedSizeTree($txCount + $txCount % 2, $hashFxn); // Compute hash of each transaction $last = ''; foreach ($block->getTransactions() as $i => $transaction) { $last = $txSerializer->serialize($transaction)->getBinary(); $tree->set($i, $last); } // Check if we need to repeat the last hash (odd number of transactions) if (!($txCount % 2 === 0)) { $tree->set($txCount, $last); } $binary = $tree->hash(); } return (new Buffer($binary))->flip(); }