示例#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;
 }
示例#2
0
 /**
  * @param BlockHeaderInterface[] $headers
  * @return HeadersBatch
  */
 public function prepareBatch(array $headers)
 {
     $countHeaders = count($headers);
     if (0 === $countHeaders) {
         return new HeadersBatch($this->chains->best($this->math), []);
     }
     $bestPrev = null;
     $firstUnknown = null;
     $hashStorage = new HashStorage();
     foreach ($headers as $i => &$head) {
         if ($this->chains->isKnownHeader($head->getPrevBlock())) {
             $bestPrev = $head->getPrevBlock();
         }
         $hash = Hash::sha256d($head->getBuffer())->flip();
         $hashStorage->attach($head, $hash);
         if ($firstUnknown === null && !$this->chains->isKnownHeader($hash)) {
             $firstUnknown = $i;
         }
     }
     if (!$bestPrev instanceof BufferInterface) {
         throw new \RuntimeException('Headers::accept(): Unknown start header');
     }
     $view = $this->chains->isTip($bestPrev);
     if ($view === false) {
         throw new \RuntimeException('Headers::accept(): Unhandled fork');
     }
     $prevIndex = $view->getIndex();
     $access = $this->chains->access($view);
     $batch = [];
     if ($firstUnknown !== null) {
         $versionInfo = $this->db->findSuperMajorityInfoByView($view);
         $forks = new Forks($this->consensus->getParams(), $prevIndex, $versionInfo);
         for ($i = $firstUnknown; $i < $countHeaders; $i++) {
             /**
              * @var BufferInterface $hash
              * @var BlockHeaderInterface $header
              */
             $header = $headers[$i];
             $hash = $hashStorage[$header];
             $this->headerCheck->check($hash, $header);
             $index = $this->getNextIndex($hash, $prevIndex, $header);
             $forks->next($index);
             $this->headerCheck->checkContextual($access, $index, $prevIndex, $forks);
             $batch[] = $index;
             $prevIndex = $index;
         }
     }
     return new HeadersBatch($view, $batch);
 }