Esempio n. 1
0
 /**
  * @param ChainState $state
  * @param ChainCache $chainView
  * @param Peer $peer
  * @param Inventory[] $items
  */
 public function advertised(ChainState $state, ChainCache $chainView, Peer $peer, array $items)
 {
     $chain = $state->getChain();
     $fetch = [];
     $lastUnknown = null;
     foreach ($items as $inv) {
         $hash = $inv->getHash();
         if ($chain->containsHash($hash)) {
             if (!$chainView->containsHash($hash)) {
                 $fetch[] = $inv;
             }
         } else {
             $lastUnknown = $hash;
         }
     }
     if (null !== $lastUnknown) {
         echo "send headers\n";
         $peer->getheaders($state->getHeadersLocator($lastUnknown));
         $this->peerState->fetch($peer)->updateBlockAvailability($state, $lastUnknown);
     }
     if (count($fetch) > 0) {
         echo 'SEND GETDATA:' . count($fetch) . '\\n';
         $peer->getdata($fetch);
     }
 }
Esempio n. 2
0
 /**
  * @param ChainState $state
  * @param Buffer $hash
  */
 public function updateBlockAvailability(ChainState $state, Buffer $hash)
 {
     $chain = $state->getChain();
     if ($chain->containsHash($hash)) {
         echo 'update peers BESTKNOWN block (' . $chain->getHeightFromHash($hash) . ')' . PHP_EOL;
         $this->save(self::INDEXBESTKNOWNBLOCK, $hash);
     } else {
         echo 'update peers HASH UNKNOWN block' . PHP_EOL;
         $this->save(self::HASHLASTUNKNOWNBLOCK, $hash);
     }
 }
Esempio n. 3
0
 /**
  * @param ChainState $state
  * @param Buffer $startHash
  * @throws \RuntimeException
  * @throws \Exception
  * @return array
  */
 private function relativeNextInventory(ChainState $state, Buffer $startHash)
 {
     $best = $state->getChain();
     if (!$best->containsHash($startHash)) {
         throw new \RuntimeException('Hash not found in this chain');
     }
     $startHeight = $best->getHeightFromHash($startHash) + 1;
     $stopHeight = min($startHeight + self::DOWNLOAD_AMOUNT, $best->getIndex()->getHeight());
     $nInFlight = count($this->inFlight);
     $request = [];
     for ($i = $startHeight; $i < $stopHeight && $nInFlight < self::MAX_IN_FLIGHT; $i++) {
         $request[] = Inventory::block($best->getHashFromHeight($i));
         $nInFlight++;
     }
     return $request;
 }
Esempio n. 4
0
 /**
  * @param ChainState $state
  * @param BlockInterface $block
  * @param Headers $headers
  * @param UtxoIdx $utxoIdx
  * @return BlockIndex
  */
 public function accept(ChainState $state, BlockInterface $block, Headers $headers, UtxoIdx $utxoIdx)
 {
     $bestBlock = $state->getLastBlock();
     if ($bestBlock->getHash() !== $block->getHeader()->getPrevBlock()) {
         throw new \RuntimeException('Blocks:accept() Block does not extend this chain!');
     }
     $index = $headers->accept($state, $block->getHeader());
     $this->blockCheck->check($block)->checkContextual($block, $bestBlock);
     //$view = $utxoIdx->fetchView($state, $block);
     $view = $this->db->fetchUtxoView($block);
     $flagP2sh = $this->consensus->scriptVerifyPayToScriptHash($bestBlock->getHeader()->getTimestamp());
     $flags = new Flags($flagP2sh ? InterpreterInterface::VERIFY_P2SH : InterpreterInterface::VERIFY_NONE);
     $nInputs = 0;
     $nFees = 0;
     $nSigOps = 0;
     $txs = $block->getTransactions();
     foreach ($block->getTransactions() as $tx) {
         $nInputs += count($tx->getInputs());
         $nSigOps += $this->blockCheck->getLegacySigOps($tx);
         if ($nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) {
             throw new \RuntimeException('Blocks::accept() - too many sigops');
         }
         if (!$tx->isCoinbase()) {
             if ($flagP2sh) {
                 $nSigOps = $this->blockCheck->getP2shSigOps($view, $tx);
                 if ($nSigOps > $this->consensus->getParams()->getMaxBlockSigOps()) {
                     throw new \RuntimeException('Blocks::accept() - too many sigops');
                 }
             }
             $fee = $this->math->sub($view->getValueIn($this->math, $tx), $tx->getValueOut());
             $nFees = $this->math->add($nFees, $fee);
             $this->blockCheck->checkInputs($view, $tx, $index->getHeight(), $flags);
         }
     }
     $this->blockCheck->checkCoinbaseSubsidy($txs[0], $nFees, $index->getHeight());
     $this->db->insertBlock($block);
     $state->updateLastBlock($index);
     return $index;
 }
Esempio n. 5
0
 /**
  * @param ChainState $state
  * @return int|string
  */
 public function getWorkRequired(ChainState $state)
 {
     $math = $this->math;
     $index = $state->getChain()->getIndex();
     if ($math->cmp($math->mod($math->add($index->getHeight(), 1), $this->params->powRetargetInterval()), 0) != 0) {
         // No change in difficulty
         return $index->getHeader()->getBits()->getInt();
     }
     // Retarget
     $heightLastRetarget = $math->sub($index->getHeight(), $math->sub($this->params->powRetargetInterval(), 1));
     $lastTime = $state->getChain()->fetchAncestor($heightLastRetarget)->getHeader()->getTimestamp();
     return $this->calculateNextWorkRequired($index, $lastTime);
 }
Esempio n. 6
0
 /**
  * @param ChainState $state
  * @param BlockHeaderInterface[] $headers
  * @return bool
  * @throws \Exception
  */
 public function acceptBatch(ChainState $state, array $headers)
 {
     $tip = $state->getChain();
     $batch = array();
     $startIndex = $tip->getIndex();
     foreach ($headers as $header) {
         if ($tip->containsHash($header->getHash())) {
             continue;
         }
         $prevIndex = $tip->getIndex();
         if ($prevIndex->getHash() !== $header->getPrevBlock()) {
             throw new \RuntimeException('Header mismatch, header.prevBlock does not refer to tip');
         }
         $index = $this->headerCheck->check($header)->checkContextual($state, $header)->makeIndex($prevIndex, $header);
         $tip->updateTip($index);
         $batch[] = $tip->getIndex();
     }
     // Do a batch update of the chain
     if (count($batch) > 0) {
         $this->db->insertIndexBatch($startIndex, $batch);
         unset($batch);
     }
     return true;
 }
Esempio n. 7
0
 public function compareChainStateWork(ChainState $a, ChainState $b)
 {
     return $this->adapter->getMath()->cmp($a->getChain()->getIndex()->getWork(), $b->getChain()->getIndex()->getWork());
 }