/** * @param NodeInterface $node * @param array $params * @return array */ public function execute(NodeInterface $node, array $params) { $chains = $node->chains(); $nChain = count($chains); $best = $chains->best(); return ['best_header' => $this->convertIndexToArray($best->getIndex()), 'best_block' => $this->convertIndexToArray($best->getLastBlock()), 'nChain' => $nChain]; }
/** * @param Container $container */ public function register(Container $container) { $headers = $this->node->headers(); $headers->on('headers', function (HeadersBatch $batch) use($container) { /** @var DbInterface $db */ $db = $container['db']; /** @var DebugInterface $debug */ $debug = $container['debug']; if (count($batch->getIndices()) > 0) { $first = $batch->getIndices()[0]; $prevIndex = $db->fetchIndex($first->getHeader()->getPrevBlock()); $versionInfo = $db->findSuperMajorityInfoByHash($prevIndex->getHash()); $forks = new Forks($this->params, $prevIndex, $versionInfo); $first = $forks->toArray(); $changes = []; foreach ($batch->getIndices() as $index) { $forks->next($index); $new = $forks->toArray(); if ($first !== $new) { $changes[] = [$index, $first, $new]; $first = $new; } } foreach ($changes as $change) { /** @var BlockIndexInterface $index */ list($index, $first, $features) = $change; $debug->log('fork.new', ['hash' => $index->getHash()->getHex(), 'height' => $index->getHeight(), 'old' => $first, 'features' => $features]); } } }); }
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 NodeInterface $node * @param array $params * @return array */ public function execute(NodeInterface $node, array $params) { if (strlen($params[self::PARAM_HASH]) !== 64) { throw new \RuntimeException('Invalid hash'); } $index = $node->chain()->fetchIndex(Buffer::hex($params[self::PARAM_HASH])); return ['header' => $this->convertIndexToArray($index)]; }
/** * @param NodeInterface $node * @param array $params * @return array */ public function execute(NodeInterface $node, array $params) { if (!is_int($params[self::PARAM_HEIGHT])) { throw new \RuntimeException('Invalid height'); } $chain = $node->chain(); $hash = $chain->getHashFromHeight($params[self::PARAM_HEIGHT]); return ['hash' => $hash->getHex()]; }
/** * @param NodeInterface $node * @param array $params * @return array */ public function execute(NodeInterface $node, array $params) { if (strlen($params[self::PARAM_TXID]) !== 64) { throw new \RuntimeException('Invalid txid field'); } $txid = Buffer::hex($params[self::PARAM_TXID], 32); $tx = $node->chain()->fetchTransaction($node->transactions(), $txid); return ['tx' => $this->convertTransactionToArray($tx)]; }
/** * @param NodeInterface $node * @param array $params * @return array */ public function execute(NodeInterface $node, array $params) { $chains = []; foreach ($node->chains()->getStates() as $state) { $bestHeaderIdx = $state->getIndex(); $bestBlockIdx = $state->getLastBlock(); $chains[] = ['best_header' => $this->convertIndexToArray($bestHeaderIdx), 'best_block' => $this->convertIndexToArray($bestBlockIdx)]; } return $chains; }
/** * ZmqDebug constructor. * @param NodeInterface $node * @param Context $context */ public function __construct(NodeInterface $node, Context $context) { $this->socket = $context->getSocket(\ZMQ::SOCKET_PUB); $this->socket->bind('tcp://127.0.0.1:5566'); $node->on('event', function ($event, array $params) { $this->log($event, $params); }); $node->headers()->on('tip', [$this, 'logTip']); $node->blocks()->on('block', [$this, 'logBlock']); $node->chains()->on('retarget', [$this, 'logRetarget']); }
/** * @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 PeerState $state * @param Peer $peer * @param Block $blockMsg */ public function onBlock(PeerState $state, Peer $peer, Block $blockMsg) { $best = $this->node->chain(); $headerIdx = $this->node->headers(); $blockIndex = $this->node->blocks(); $checkSignatures = (bool) $this->config->getItem('config', 'check_signatures', true); $checkSize = (bool) $this->config->getItem('config', 'check_block_size', true); $checkMerkleRoot = (bool) $this->config->getItem('config', 'check_merkle_root', true); try { $index = $blockIndex->accept($blockMsg->getBlock(), $best, $headerIdx, $checkSignatures, $checkSize, $checkMerkleRoot); $this->blockDownload->received($best, $peer, $index->getHash()); } catch (\Exception $e) { $header = $blockMsg->getBlock()->getHeader(); $this->node->emit('event', ['error.onBlock', ['ip' => $peer->getRemoteAddress()->getIp(), 'hash' => $header->getHash()->getHex(), 'error' => $e->getMessage() . PHP_EOL . $e->getTraceAsString()]]); } }
/** * @param PeerState $state * @param Peer $peer * @param Headers $headersMsg */ public function onHeaders(PeerState $state, Peer $peer, Headers $headersMsg) { $headers = $this->node->headers(); try { $vHeaders = $headersMsg->getHeaders(); $batch = $headers->prepareBatch($vHeaders); $count = count($batch->getIndices()); if ($count > 0) { $headers->applyBatch($batch); $view = $batch->getTip(); $indices = $batch->getIndices(); $indexLast = end($indices); $state->updateBlockAvailability($view, $indexLast->getHash()); if ($count >= 1999) { $peer->getheaders($view->getHeadersLocator()); } } $this->emit('headers', [$state, $peer, $batch]); } catch (\Exception $e) { $this->debug->log('error.onHeaders', ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]); } }
/** * @param NodeInterface $node * @param array $params * @return array */ public function execute(NodeInterface $node, array $params) { $this->loop->stop(); $node->stop(); return ['message' => 'Shutting down']; }