Exemplo n.º 1
0
 /**
  * @param BlockInterface $block
  * @param TransactionSerializerInterface $txSerializer
  * @return BlockData
  */
 public function parseUtxos(BlockInterface $block, TransactionSerializerInterface $txSerializer)
 {
     $blockData = new BlockData();
     $unknown = [];
     $hashStorage = new HashStorage();
     // Record every Outpoint required for the block.
     foreach ($block->getTransactions() as $t => $tx) {
         if ($tx->isCoinbase()) {
             continue;
         }
         foreach ($tx->getInputs() as $in) {
             $outpoint = $in->getOutPoint();
             $unknown[$outpoint->getTxId()->getBinary() . $outpoint->getVout()] = $outpoint;
         }
     }
     foreach ($block->getTransactions() as $tx) {
         /** @var BufferInterface $buffer */
         $buffer = $txSerializer->serialize($tx);
         $hash = Hash::sha256d($buffer)->flip();
         $hashStorage->attach($tx, $hash);
         $hashBin = $hash->getBinary();
         foreach ($tx->getOutputs() as $i => $out) {
             $lookup = $hashBin . $i;
             if (isset($unknown[$lookup])) {
                 // Remove unknown outpoints which consume this output
                 $outpoint = $unknown[$lookup];
                 $utxo = new Utxo($outpoint, $out);
                 unset($unknown[$lookup]);
             } else {
                 // Record new utxos which are not consumed in the same block
                 $utxo = new Utxo(new OutPoint($hash, $i), $out);
                 $blockData->remainingNew[] = $utxo;
             }
             // All utxos produced are stored
             $blockData->parsedUtxos[] = $utxo;
         }
     }
     $blockData->requiredOutpoints = array_values($unknown);
     $blockData->hashStorage = $hashStorage;
     return $blockData;
 }
Exemplo n.º 2
0
 /**
  * @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();
 }