/** * @param ConfigProviderInterface $config * @return StorageProvider */ protected function loadStorageProvider(ConfigProviderInterface $config) { if ($config->getItem('config', 'storage-redis', false)) { $redis = new \Redis(); $redis->connect($config->getItem('redis', 'host', $this->defaultRedisHost)); $mkCache = StorageProvider::makeRedis($redis); } else { throw new \RuntimeException('No storage module loaded'); } return new StorageProvider($mkCache); }
/** * @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 Container $container * @param NodeInterface $node * @param LoopInterface $loop * @param ConfigProviderInterface $config * @param DbInterface $db */ public function setupServices(Container $container, NodeInterface $node, LoopInterface $loop, ConfigProviderInterface $config, DbInterface $db) { // Configure commands exposed by UserControl & WebSocket /** @var CommandInterface[] $basicCommands */ $basicCommands = [new InfoCommand(), new GetTxCommand(), new GetHeaderCommand(), new GetBlockHashCommand(), new ChainsCommand()]; $consoleCommands = $basicCommands; $consoleCommands[] = new ShutdownCommand($loop); // Create services $services = [new LoopServiceProvider($loop), new ConfigServiceProvider($config), new DbServiceProvider($db), new ZmqServiceProvider(), new UserControlServiceProvider($node, $consoleCommands)]; $p2p = $config->getItem('config', 'p2p', true); if ($p2p) { $services[] = new P2PServiceProvider($node); $services[] = new P2PInvServiceProvider(); $services[] = new P2PHeadersServiceProvider($node); $services[] = new P2PBlocksServiceProvider($node); $services[] = new P2PPingServiceProvider(); } $websocket = $config->getItem('config', 'websocket', false); if ($websocket) { $services[] = new WebSocketServiceProvider($node, $basicCommands); } foreach ($services as $service) { $container->register($service); } // Launch services $container['debug']; $container['userControl']; if ($websocket) { $container['websocket']; } if ($p2p) { $container['p2p']->run(); } }
/** * @param Peer $peer * @return bool */ public function checkAcceptablePeer(Peer $peer) { $remote = $peer->getRemoteVersion(); if ($remote->getVersion() < Protocol::GETHEADERS) { return false; } if ($this->config->getItem('config', 'download_blocks', true) && $remote->getServices() & Services::NETWORK == 0) { return false; } return true; }
/** * */ public function start() { $dns = $this->netFactory->getDns(); $peerFactory = $this->netFactory->getPeerFactory($dns); $handler = $peerFactory->getPacketHandler(); $locator = $peerFactory->getLocator(); $txRelay = $this->config->getItem('config', 'tx_relay', false); $manager = $peerFactory->getManager($txRelay); $manager->on('outbound', function (Peer $peer) { $this->peersOutbound->add($peer); }); $manager->on('inbound', function (Peer $peer) { $this->peersInbound->add($peer); }); $manager->registerHandler($handler); // Setup listener if required if ($this->config->getItem('config', 'listen', '0')) { echo ' [App - networking] enable listener'; $server = new \React\Socket\Server($this->loop); $listener = $peerFactory->getListener($server); $manager->registerListener($listener); } $handler->on('ping', function (Peer $peer, Ping $ping) { $peer->pong($ping); }); // Only for outbound peers $handler->on('outbound', function (Peer $peer) { $peer->on('msg', function (Peer $peer, NetworkMessage $msg) { $payload = $msg->getPayload(); if ($msg->getCommand() === 'block') { /** @var Block $payload */ echo ' [Peer] ' . $peer->getRemoteAddr()->getIp() . ' - block - ' . $payload->getBlock()->getHeader()->getHash()->getHex() . PHP_EOL; } else { echo ' [Peer] ' . $peer->getRemoteAddr()->getIp() . ' - ' . $msg->getCommand() . PHP_EOL; } }); $peer->on('block', array($this, 'onBlock')); $peer->on('inv', array($this, 'onInv')); $peer->on('getheaders', array($this, 'onGetHeaders')); $peer->on('headers', array($this, 'onHeaders')); }); $locator->queryDnsSeeds(1)->then(function (Locator $locator) use($manager, $handler) { for ($i = 0; $i < 1; $i++) { $manager->connectNextPeer($locator)->then(function (Peer $peer) { $chain = $this->chain(); $height = $chain->getChain()->getIndex()->getHeight(); $peer->getheaders($chain->getLocator($height - 1)); }); } }, function () { echo 'ERROR'; }); }
/** * @param ConfigProviderInterface $config * @param bool|false $debug */ public function __construct(ConfigProviderInterface $config, $debug = false) { $this->debug = $debug; $driver = $config->getItem('db', 'driver'); $host = $config->getItem('db', 'host'); $username = $config->getItem('db', 'username'); $password = $config->getItem('db', 'password'); $database = $config->getItem('db', 'database'); $this->dbh = new \PDO("{$driver}:host={$host};dbname={$database}", $username, $password); $this->dbh->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); }
/** * @param ConfigProviderInterface $config * @return Db */ public static function create(ConfigProviderInterface $config) { $driver = $config->getItem('db', 'driver'); $host = $config->getItem('db', 'host'); $username = $config->getItem('db', 'username'); $password = $config->getItem('db', 'password'); $database = $config->getItem('db', 'database'); $dbh = new \PDO("{$driver}:host={$host};dbname={$database}", $username, $password); return new self($config, $dbh); }
/** * Bind config item if not already defined * * @param ConfigProviderInterface $conf * @param $abstract * @param $section * @param $item * @param $default */ public function bindFromConfigIf(ConfigProviderInterface $conf, $abstract, $section, $item, $default) { $class = $conf->getItem($section, $item, $default); if ($class !== null) { $this->bindIf($abstract, $class, true); } }