Пример #1
0
 /**
  * @param BlockIndex $index
  */
 public function updateLastBlock(BlockIndex $index)
 {
     if ($this->lastBlock->getHash() !== $index->getHeader()->getPrevBlock()) {
         throw new \RuntimeException('UpdateLastBlock: Block does not extend this chain');
     }
     if ($this->lastBlock->getHeight() != $index->getHeight() - 1) {
         throw new \RuntimeException('UpdateLastBlock: Incorrect chain height' . ($index->getHeight() - 1));
     }
     $this->lastBlock = $index;
 }
Пример #2
0
 /**
  * @param BlockIndex $index
  */
 public function add(BlockIndex $index)
 {
     if ($index->getHeader()->getPrevBlock() !== $this->getHash($index->getHeight() - 1)->getHex()) {
         throw new \RuntimeException('ChainCache: New BlockIndex does not refer to last');
     }
     $binary = hex2bin($index->getHash());
     $this->hashByHeight[] = $binary;
     $this->heightByHash[$binary] = $index->getHeight();
 }
Пример #3
0
 /**
  * @param BlockIndex $index
  */
 public function updateTip(BlockIndex $index)
 {
     if ($this->index->getHash() !== $index->getHeader()->getPrevBlock()) {
         throw new \RuntimeException('Header: Header does not extend this chain');
     }
     if ($index->getHeight() - 1 != $this->index->getHeight()) {
         throw new \RuntimeException('Header: Incorrect chain height');
     }
     $this->chainCache->add($index);
     $this->index = $index;
 }
Пример #4
0
 public function testBlockIndex()
 {
     $headerHex = '0100000000000000000000000000000000000000000000000000000000000000000000003ba3edfd7a7b12b27ac72c3e67768f617fc81bc3888a51323a9fb8aa4b1e5e4a29ab5f49ffff001d1dac2b7c';
     $header = BlockHeaderFactory::fromHex($headerHex);
     $hash = $header->getHash();
     $height = 0;
     $work = 0;
     $index = new BlockIndex($hash, $height, $work, $header);
     $this->assertEquals($hash, $index->getHash());
     $this->assertEquals($height, $index->getHeight());
     $this->assertEquals($work, $index->getWork());
     $this->assertSame($header, $index->getHeader());
 }
Пример #5
0
 /**
  * @param BlockIndex $startIndex
  * @param BlockIndex[] $index
  * @return bool
  * @throws \Exception
  */
 public function insertIndexBatch(BlockIndex $startIndex, array $index)
 {
     if ($this->debug) {
         echo "db: called insertIndexBATCH\n";
     }
     if (null == $this->fetchLftStmt) {
         $this->fetchLftStmt = $this->dbh->prepare('SELECT lft FROM headerIndex WHERE hash = :prevBlock');
         $this->updateIndicesStmt = $this->dbh->prepare('
             UPDATE headerIndex SET rgt = rgt + :nTimes2 WHERE rgt > :myLeft ;
             UPDATE headerIndex SET lft = lft + :nTimes2 WHERE lft > :myLeft ;
         ');
     }
     $fetchParent = $this->fetchLftStmt;
     $updateIndices = $this->updateIndicesStmt;
     $fetchParent->bindParam(':prevBlock', $startIndex->getHash());
     if ($fetchParent->execute()) {
         foreach ($fetchParent->fetchAll() as $record) {
             $myLeft = $record['lft'];
         }
     }
     $fetchParent->closeCursor();
     if (!isset($myLeft)) {
         throw new \RuntimeException('Failed to extract header position');
     }
     $totalN = count($index);
     $nTimesTwo = 2 * $totalN;
     $leftOffset = $myLeft;
     $rightOffset = $myLeft + $nTimesTwo;
     $this->dbh->beginTransaction();
     try {
         if ($updateIndices->execute(['nTimes2' => $nTimesTwo, 'myLeft' => $myLeft])) {
             $updateIndices->closeCursor();
             $values = [];
             $query = [];
             foreach ($index as $c => $i) {
                 $query[] = "(:hash{$c} , :height{$c} , :work{$c} ,\n                    :version{$c} , :prevBlock{$c} , :merkleRoot{$c} ,\n                    :nBits{$c} , :nTimestamp{$c} , :nNonce{$c} ,\n                    :lft{$c} , :rgt{$c} )";
                 $values['hash' . $c] = $i->getHash();
                 $values['height' . $c] = $i->getHeight();
                 $values['work' . $c] = $i->getWork();
                 $header = $i->getHeader();
                 $values['version' . $c] = $header->getVersion();
                 $values['prevBlock' . $c] = $header->getPrevBlock();
                 $values['merkleRoot' . $c] = $header->getMerkleRoot();
                 $values['nBits' . $c] = $header->getBits()->getInt();
                 $values['nTimestamp' . $c] = $header->getTimestamp();
                 $values['nNonce' . $c] = $header->getNonce();
                 $values['lft' . $c] = $leftOffset + 1 + $c;
                 $values['rgt' . $c] = $rightOffset - $c;
             }
             $stmt = $this->dbh->prepare("\n                  INSERT INTO headerIndex (hash, height, work, version, prevBlock, merkleRoot, nBits, nTimestamp, nNonce, lft, rgt )\n                  VALUES " . implode(', ', $query));
             $count = $stmt->execute($values);
             $this->dbh->commit();
             if ($count === $totalN) {
                 return true;
             } else {
                 throw new \RuntimeException('Strange: Failed to update chain!');
             }
         }
     } catch (\Exception $e) {
         $this->dbh->rollBack();
         throw $e;
     }
     throw new \RuntimeException('Failed to update chain!');
 }