/** * @param BufferInterface $hash * @return BlockIndexInterface */ public function fetchIndex(BufferInterface $hash) { if (!$this->view->containsHash($hash)) { throw new \RuntimeException('Index by this hash not known'); } return $this->db->fetchIndex($hash); }
public function __construct(NodeInterface $node, Container $container) { $this->db = $container['db']; $this->retargetDb = new RetargetDb($this->db->getPdo()); $this->math = Bitcoin::getMath(); $this->consensus = new Consensus(Bitcoin::getMath(), new Params(Bitcoin::getMath())); $node->chains()->on('retarget', [$this, 'onRetarget']); }
/** * @param PeerState $state * @param Peer $peer * @param GetHeaders $getHeaders */ public function onGetHeaders(PeerState $state, Peer $peer, GetHeaders $getHeaders) { return; $chain = $this->node->chain(); if ($chain->getIndex()->getHeader()->getTimestamp() >= time() - 60 * 60 * 24) { $locator = $getHeaders->getLocator(); if (count($locator->getHashes()) === 0) { $start = $locator->getHashStop(); } else { $start = $this->db->findFork($chain, $locator); } $headers = $this->db->fetchNextHeaders($start); $peer->headers($headers); $this->debug->log('peer.sentheaders', ['count' => count($headers), 'start' => $start->getHex()]); } }
/** * @param OutPointInterface[] $requiredOutpoints * @return UtxoInterface[] */ public function fetchView(array $requiredOutpoints) { try { $utxos = []; $required = []; $cacheHits = []; foreach ($requiredOutpoints as $c => $outpoint) { $key = $this->outpointSerializer->serialize($outpoint)->getBinary(); if ($this->set->contains($key)) { list($value, $scriptPubKey) = $this->set->fetch($key); $cacheHits[] = $key; $utxos[] = new Utxo($outpoint, new TransactionOutput($value, new Script(new Buffer($scriptPubKey)))); } else { $required[] = $outpoint; } } if (empty($required) === false) { $utxos = array_merge($utxos, $this->db->fetchUtxoDbList($this->outpointSerializer, $required)); } if ($this->caching) { $this->cacheHits = $cacheHits; } return $utxos; } catch (\Exception $e) { echo $e->getMessage() . PHP_EOL; throw new \RuntimeException('Failed to find UTXOS in set'); } }
/** * @param HeadersBatch $batch * @return $this * @throws \Exception */ public function applyBatch(HeadersBatch $batch) { $indices = $batch->getIndices(); if (count($indices) === 0) { return $this; } $this->db->insertHeaderBatch($batch); $tip = $batch->getTip(); foreach ($batch->getIndices() as $index) { $tip->updateTip($index); } $this->emit('tip', [$batch]); return $this; }
/** * @param BlockInterface $block * @param HeaderChainViewInterface $chainView * @param Headers $headers * @param bool $checkSignatures * @param bool $checkSize * @param bool $checkMerkleRoot * @return BlockIndexInterface */ public function accept(BlockInterface $block, HeaderChainViewInterface $chainView, Headers $headers, $checkSignatures = true, $checkSize = true, $checkMerkleRoot = true) { $hash = $block->getHeader()->getHash(); $index = $headers->accept($hash, $block->getHeader(), true); $outpointSerializer = new CachingOutPointSerializer(); $txSerializer = new CachingTransactionSerializer(new TransactionInputSerializer($outpointSerializer)); $blockSerializer = new CachingBlockSerializer($this->math, new BlockHeaderSerializer(), $txSerializer); $utxoSet = new UtxoSet($this->db, $outpointSerializer); $blockData = $this->prepareBatch($block, $txSerializer, $utxoSet); $this->blockCheck->check($block, $txSerializer, $blockSerializer, $checkSize, $checkMerkleRoot)->checkContextual($block, $chainView->getLastBlock()); $forks = $this->prepareForks($chainView, $index); $this->checkBlockData($block, $blockData, $checkSignatures, $forks->getFlags(), $index->getHeight()); $this->db->transaction(function () use($hash, $block, $blockSerializer, $utxoSet, $blockData) { $this->db->insertBlock($hash, $block, $blockSerializer); $utxoSet->applyBlock($blockData); }); $chainView->blocks()->updateTip($index); $forks->next($index); $this->emit('block', [$index, $block, $blockData]); print_r($outpointSerializer->stats()); return $index; }
/** * @param DbInterface $db * @param ChainSegment $segment * @throws \Exception */ private function processSegment(DbInterface $db, ChainSegment $segment) { $id = $segment->getId(); if (isset($this->segmentBlock[$segment])) { throw new \Exception('Already processed this segment'); } $segCount = $segment->getLast()->getHeight() - $segment->getStart() + 1; $hashes = $db->loadHashesForSegment($id); if (count($hashes) !== $segCount) { throw new \Exception('Not enough hashes found for segment'); } $this->hashStorage[$id] = []; foreach ($hashes as $row) { $this->hashStorage[$id][$row['hash']] = $row['height']; $this->heightStorage[$id][$row['height']] = $row['hash']; } if ($segment->getStart() != 0) { $ancestor = $db->loadSegmentAncestor($id, $segment->getStart()); if (!isset($this->segments[$ancestor])) { throw new \RuntimeException('Failed to link segment'); } $this->chainLink[$id] = $ancestor; } $this->segmentBlock[$segment] = $this->db->findSegmentBestBlock($this->getHistory($segment)); }
/** * @param callable $function */ public function transaction(callable $function) { echo __FUNCTION__ . PHP_EOL; $this->db->transaction($function); }
/** * @param BufferInterface $tipHash * @param BufferInterface $txid * @return TransactionInterface */ public function fetch(BufferInterface $tipHash, BufferInterface $txid) { return $this->db->getTransaction($tipHash, $txid); }
/** * @param OutPointInterface[] $required * @return UtxoInterface[] */ public function fetchView(array $required) { return $this->db->fetchUtxoDbList($this->outpointSerializer, $required); }
/** * @return void */ public function stop() { $this->db->stop(); }