Exemplo n.º 1
0
 /**
  * @param BlockInterface $block
  * @return $this
  */
 public function check(BlockInterface $block)
 {
     $header = $block->getHeader();
     if ($block->getMerkleRoot() !== $header->getMerkleRoot()) {
         throw new \RuntimeException('Blocks::check(): failed to verify merkle root');
     }
     $transactions = $block->getTransactions();
     $txCount = count($transactions);
     if ($txCount == 0 || $block->getBuffer()->getSize() > $this->params->maxBlockSizeBytes()) {
         throw new \RuntimeException('Blocks::check(): Zero transactions, or block exceeds max size');
     }
     // The first transaction is coinbase, and only the first transaction is coinbase.
     if (!$transactions[0]->isCoinbase()) {
         throw new \RuntimeException('Blocks::check(): First transaction was not coinbase');
     }
     for ($i = 1; $i < $txCount; $i++) {
         if ($transactions->offsetGet($i)->isCoinbase()) {
             throw new \RuntimeException('Blocks::check(): more than one coinbase');
         }
     }
     $nSigOps = 0;
     foreach ($transactions as $transaction) {
         if (!$this->checkTransaction($transaction)) {
             throw new \RuntimeException('Blocks::check(): failed checkTransaction');
         }
         $nSigOps += $this->getLegacySigOps($transaction);
     }
     if ($this->math->cmp($nSigOps, $this->params->getMaxBlockSigOps()) > 0) {
         throw new \RuntimeException('Blocks::check(): out-of-bounds sigop count');
     }
     return $this;
 }
Exemplo n.º 2
0
 /**
  *
  */
 private function update()
 {
     $header = $this->index->getHeader();
     // Check all active features
     if ($header->getTimestamp() >= $this->params->p2shActivateTime()) {
         $this->p2sh = true;
     }
     $hash = $this->index->getHash()->getBinary();
     $this->bip30 = !($this->index->getHeight() == 91842 && $hash == pack("H*", "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec") || $this->index->getHeight() == 91880 && $hash == pack("H*", "00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"));
     $highest = $this->majorityVersion();
     if ($highest >= 2) {
         $this->bip34 = true;
     }
     if ($highest >= 3) {
         $this->derSig = true;
     }
     if ($highest >= 4) {
         $this->cltv = true;
     }
     // Calculate flags
     $this->flags = $this->p2sh ? InterpreterInterface::VERIFY_NONE : InterpreterInterface::VERIFY_P2SH;
     if ($this->derSig) {
         $this->flags |= InterpreterInterface::VERIFY_DERSIG;
     }
     if ($this->cltv) {
         $this->flags |= InterpreterInterface::VERIFY_CHECKLOCKTIMEVERIFY;
     }
 }
Exemplo n.º 3
0
 /**
  * @param ChainSegment $segment
  * @param BlockIndexInterface $index
  */
 public function updateSegment(ChainSegment $segment, BlockIndexInterface $index)
 {
     $prevBits = $segment->getLast()->getHeader()->getBits();
     $segment->next($index);
     $this->hashStorage[$segment->getId()][$index->getHash()->getBinary()] = $index->getHeight();
     $this->heightStorage[$segment->getId()][$index->getHeight()] = $index->getHash()->getBinary();
     if ($index->getHeight() % $this->params->powRetargetInterval() === 0) {
         $this->emit('retarget', [$segment, $prevBits, $index]);
     }
     $this->updateGreatestWork();
 }
Exemplo n.º 4
0
 /**
  * @param int $minVersion
  * @param int $startHeight
  * @param int $nRequired
  * @param Index\Blocks $blocks
  * @return bool
  */
 public function isSuperMajority($minVersion, $startHeight, Index\Blocks $blocks, $nRequired)
 {
     $nFound = 0;
     $window = $this->params->majorityWindow();
     for ($i = 0; $i < $window && $nFound < $nRequired && ($index = $blocks->fetchByHeight($startHeight - $i)); $i++) {
         if ($this->math->cmp($index->getHeader()->getVersion(), $minVersion)) {
             $nFound++;
         }
     }
     return $nFound >= $nRequired;
 }
Exemplo n.º 5
0
 /**
  * BetterNode constructor.
  * @param ConfigProviderInterface $config
  * @param ParamsInterface $params
  * @param DbInterface $db
  */
 public function __construct(ConfigProviderInterface $config, ParamsInterface $params, DbInterface $db)
 {
     $math = Bitcoin::getMath();
     $adapter = Bitcoin::getEcAdapter($math);
     $this->chains = new ChainContainer($math, $params);
     $consensus = new Consensus($math, $params);
     $pow = new ProofOfWork($math, $params);
     $this->headers = new Index\Headers($db, $adapter, $this->chains, $consensus, $pow);
     $this->blocks = new Index\Blocks($db, $config, $adapter, $this->chains, $consensus);
     $this->transactions = new Index\Transactions($db);
     $genesis = $params->getGenesisBlock();
     $this->headers->init($genesis->getHeader());
     $this->blocks->init($genesis);
     $this->db = $db;
     $segments = $this->db->fetchChainSegments();
     foreach ($segments as $segment) {
         $this->chains->addSegment($segment);
     }
     $this->chains->initialize($this->db);
 }
Exemplo n.º 6
0
 /**
  * @param $timeFirstBlock
  * @param BlockHeaderInterface $header
  * @return mixed
  */
 public function calculateWorkTimespan($timeFirstBlock, BlockHeaderInterface $header)
 {
     $timespan = $header->getTimestamp() - $timeFirstBlock;
     $lowest = $this->params->powTargetTimespan() / 4;
     $highest = $this->params->powTargetTimespan() * 4;
     if ($timespan < $lowest) {
         $timespan = $lowest;
     }
     if ($timespan > $highest) {
         $timespan = $highest;
     }
     return $timespan;
 }
Exemplo n.º 7
0
 /**
  * @return int|string
  */
 public function getMaxTarget()
 {
     return $this->getTarget(Buffer::int($this->params->powBitsLimit(), 4, $this->math));
 }
Exemplo n.º 8
0
 /**
  * @param ParamsInterface $params
  * @param LoopInterface $loop
  */
 public function __construct(ParamsInterface $params, LoopInterface $loop)
 {
     echo ' [App] start ' . PHP_EOL;
     $start = microtime(true);
     $math = Bitcoin::getMath();
     $adapter = Bitcoin::getEcAdapter($math);
     $zmq = new ZMQContext($loop);
     $this->initControl($zmq)->initConfig();
     $this->loop = $loop;
     $this->params = $params;
     $this->adapter = $adapter;
     $this->chains = new Chains($adapter);
     $this->inventory = new KnownInventory();
     $this->peerState = new PeerStateCollection();
     $this->peersInbound = new Peers();
     $this->peersOutbound = new Peers();
     $this->netFactory = new NetworkingFactory($loop);
     $this->db = new Db($this->config, false);
     $consensus = new Consensus($math, $params);
     $zmqScript = new ZmqScriptCheck(new \ZMQContext());
     $this->headers = new Index\Headers($this->db, $consensus, $math, new HeaderCheck($consensus, $adapter, new ProofOfWork($math, $params)));
     $this->blocks = new Index\Blocks($this->db, $adapter, $consensus, new BlockCheck($consensus, $adapter, $zmqScript));
     $genesis = $params->getGenesisBlock();
     $this->headers->init($genesis->getHeader());
     $this->blocks->init($genesis);
     $this->initChainState();
     $this->utxo = new Index\UtxoIdx($this->chains, $this->db);
     $this->blockDownload = new BlockDownloader($this->chains, $this->peerState, $this->peersOutbound);
     $this->on('blocks.syncing', function () {
         echo ' [App] ... BLOCKS: syncing' . PHP_EOL;
     });
     $this->on('headers.syncing', function () {
         echo ' [App] ... HEADERS: syncing' . PHP_EOL;
     });
     $this->on('headers.synced', function () {
         echo ' [App] ... HEADERS: synced!' . PHP_EOL;
     });
     echo ' [App] Startup took: ' . (microtime(true) - $start) . ' seconds ' . PHP_EOL;
 }