示例#1
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();
 }
示例#2
0
 public function testIsNext()
 {
     $first = new BlockIndex(new Buffer('aa', 32), 0, 0, new BlockHeader(0, new Buffer('', 32), new Buffer('', 32), 0, new Buffer(), 0));
     $nextGood = new BlockIndex(new Buffer('bb'), 1, 0, new BlockHeader(0, new Buffer('aa', 32), new Buffer('', 32), 0, new Buffer(), 0));
     $nextBadHeight = new BlockIndex(Buffer::hex('bc', 32), 222, 0, new BlockHeader(0, new Buffer('aa', 32), new Buffer('', 32), 0, new Buffer(), 0));
     $nextBadHash = new BlockIndex(Buffer::hex('bd', 32), 1, 0, new BlockHeader(0, new Buffer('22', 32), new Buffer('', 32), 0, new Buffer(), 0));
     $this->assertFalse($first->isNext($nextBadHash));
     $this->assertFalse($first->isNext($nextBadHeight));
     $this->assertTrue($first->isNext($nextGood));
 }
示例#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
 /**
  * @param BlockIndex $prevIndex
  * @param $timeFirstBlock
  * @return int|string
  */
 public function calculateNextWorkRequired(BlockIndex $prevIndex, $timeFirstBlock)
 {
     $header = $prevIndex->getHeader();
     $math = $this->math;
     $timespan = $math->sub($header->getTimestamp(), $timeFirstBlock);
     $lowest = $math->div($this->params->powTargetTimespan(), 4);
     $highest = $math->mul($this->params->powTargetTimespan(), 4);
     if ($math->cmp($timespan, $lowest) < 0) {
         $timespan = $lowest;
     }
     if ($math->cmp($timespan, $highest) > 0) {
         $timespan = $highest;
     }
     $target = $math->compact()->set($header->getBits()->getInt());
     $limit = $this->math->compact()->set($this->params->powBitsLimit());
     $new = bcdiv(bcmul($target, $timespan), $this->params->powTargetTimespan());
     if ($math->cmp($new, $limit) > 0) {
         $new = $limit;
     }
     return $math->compact()->read($new, false);
 }
示例#5
0
 /**
  * @param Buffer|null $hashStop
  * @return BlockLocator
  */
 public function getBlockLocator(Buffer $hashStop = null)
 {
     echo 'Produce Blocks locator (' . $this->lastBlock->getHeight() . ') ' . PHP_EOL;
     return $this->getLocator($this->lastBlock->getHeight(), $hashStop);
 }
示例#6
0
 /**
  * @param BlockIndex $prevIndex
  * @param BlockHeaderInterface $header
  * @return BlockIndex
  */
 public function makeIndex(BlockIndex $prevIndex, BlockHeaderInterface $header)
 {
     return new BlockIndex($header->getHash()->getHex(), $this->math->add($prevIndex->getHeight(), 1), $this->math->add($this->pow->getWork($header->getBits()), $prevIndex->getWork()), $header);
 }
示例#7
0
文件: Db.php 项目: sbwdlihao/node-php
 /**
  * @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!');
 }
示例#8
0
 /**
  * @param BlockInterface $block
  * @param BlockIndex $prevBlockIndex
  * @return bool
  */
 public function checkContextual(BlockInterface $block, BlockIndex $prevBlockIndex)
 {
     $newHeight = $prevBlockIndex->getHeight() + 1;
     $newTime = $block->getHeader()->getTimestamp();
     foreach ($block->getTransactions() as $transaction) {
         if (!$this->checkTransactionIsFinal($transaction, $newHeight, $newTime)) {
             throw new \RuntimeException('Block contains a non-final transaction');
         }
     }
     return $this;
 }