Ejemplo n.º 1
0
 private boolean inMainChain(Block block) {
   Block b = this.lastBlock;
   while (b != null && b.getBlockNo() > block.getBlockNo()) {
     b = AbstractDb.blockProvider.getBlock(b.getBlockPrev());
   }
   return b != null && Arrays.equals(b.getBlockHash(), block.getBlockHash());
 }
Ejemplo n.º 2
0
  private Block getSameParent(Block block1, Block block2) {
    Block b1 = block1;
    Block b2 = block2;

    while (b1 != null && b2 != null && !Arrays.equals(b1.getBlockHash(), b2.getBlockHash())) {
      if (b1.getBlockNo() == 0 || b1.getBlockNo() >= b2.getBlockNo()) {
        b1 = AbstractDb.blockProvider.getBlock(b1.getBlockPrev());
      }
      if (b1.getBlockNo() < b2.getBlockNo()) {
        b2 = AbstractDb.blockProvider.getBlock(b2.getBlockPrev());
      }
    }
    return b1;
  }
Ejemplo n.º 3
0
  public int relayedBlockHeadersForMainChain(List<Block> blocks) {
    if (blocks == null || blocks.size() == 0) {
      return 0;
    }
    ArrayList<Block> blocksToAdd = new ArrayList<Block>();
    Block prev = getLastBlock();
    if (prev == null) {
      log.warn("pre block is null");
      return 0;
    }
    for (int i = 0; i < blocks.size(); i++) {
      Block block = blocks.get(i);
      if (!Arrays.equals(prev.getBlockHash(), block.getBlockPrev())) {
        Block alreadyIn = getBlock(block.getBlockHash());
        if (alreadyIn != null) {
          log.debug("Block is already in, No." + alreadyIn.getBlockNo());
          continue;
        } else {
          this.singleBlocks.put(block.getBlockHash(), block);
          break;
        }
      }
      block.setBlockNo(prev.getBlockNo() + 1);
      try {
        block.verifyDifficultyFromPreviousBlock(prev);
      } catch (Exception e) {
        e.printStackTrace();
        break;
      }

      block.setMain(true);
      blocksToAdd.add(block);
      prev = block;
    }
    if (blocksToAdd.size() > 0) {
      addBlocks(blocksToAdd);
      lastBlock = blocksToAdd.get(blocksToAdd.size() - 1);
    }
    return blocksToAdd.size();
  }
Ejemplo n.º 4
0
  public boolean rollbackBlock(int blockNo) {
    log.warn("block chain roll back to " + blockNo);
    if (blockNo > this.lastBlock.getBlockNo()) return false;
    int delta = this.lastBlock.getBlockNo() - blockNo;
    if (delta >= BitherjSettings.BLOCK_DIFFICULTY_INTERVAL || delta >= this.getBlockCount())
      return false;

    List<Block> blocks = AbstractDb.blockProvider.getBlocksFrom(blockNo);
    // DDLogWarn(@"roll back block from %d to %d", self.lastBlock.height, blockNo);

    for (Block block : blocks) {
      AbstractDb.blockProvider.removeBlock(block.getBlockHash());

      if (block.isMain()) {
        AbstractDb.txProvider.unConfirmTxByBlockNo(block.getBlockNo());
      }
    }
    this.lastBlock = AbstractDb.blockProvider.getLastBlock();
    return true;
  }
Ejemplo n.º 5
0
  public List<byte[]> getBlockLocatorArray() {
    // append 10 most recent block hashes, descending, then continue appending, doubling the step
    // back each time,
    // finishing with the genesis block (top, -1, -2, -3, -4, -5, -6, -7, -8, -9, -11, -15, -23,
    // -39, -71, -135, ..., 0)
    ArrayList<byte[]> locators = new ArrayList<byte[]>();
    int step = 1, start = 0;
    Block b = this.lastBlock;

    while (b != null && b.getBlockNo() > 0) {
      locators.add(b.getBlockHash());
      if (++start >= 10) step *= 2;

      for (int i = 0; b != null && i < step; i++) {
        b = AbstractDb.blockProvider.getMainChainBlock(b.getBlockPrev());
      }
    }
    locators.add(BitherjSettings.GENESIS_BLOCK_HASH);

    return locators;
  }
Ejemplo n.º 6
0
  public int relayedBlocks(List<Block> blocks) throws VerificationException {
    if (blocks == null || blocks.size() == 0) {
      return 0;
    }
    Block prev = null;
    Block first = blocks.get(0);
    int rollbackBlockNo = 0;
    if (Arrays.equals(first.getBlockPrev(), this.getLastBlock().getBlockHash())) {
      prev = this.getLastBlock();
    } else if (AbstractDb.blockProvider.getMainChainBlock(first.getBlockPrev()) != null) {
      prev = this.getSameParent(first, this.getLastBlock());
      rollbackBlockNo = prev.getBlockNo();
    }
    if (prev == null) {
      return 0;
    }
    for (Block block : blocks) {
      if (!Arrays.equals(block.getBlockPrev(), prev.getBlockHash())) {
        return 0;
      }
      block.setBlockNo(prev.getBlockNo() + 1);
      try {
        int transitionTime = 0;
        if (block.getBlockNo() % BitherjSettings.BLOCK_DIFFICULTY_INTERVAL == 0) {
          // We need to find a block far back in the chain. It's OK that this is expensive because
          // it only occurs every
          // two weeks after the initial block chain download.
          long now = System.currentTimeMillis();
          Block cursor = first;
          for (int i = 0;
              i
                  < BitherjSettings.BLOCK_DIFFICULTY_INTERVAL
                      - block.getBlockNo()
                      + first.getBlockNo();
              i++) {
            if (cursor == null) {
              // This should never happen. If it does, it means we are following an incorrect or
              // busted chain.
              throw new VerificationException(
                  "Difficulty transition point but we did not find a way back to the genesis block.");
            }
            cursor = getBlock(cursor.getBlockPrev());
          }
          long elapsed = System.currentTimeMillis() - now;
          if (elapsed > 50) log.info("Difficulty transition traversal took {}msec", elapsed);

          transitionTime = cursor.getBlockTime();
        }
        block.verifyDifficultyFromPreviousBlock(prev, transitionTime);
      } catch (Exception e) {
        e.printStackTrace();
        return 0;
      }

      block.setMain(true);
      prev = block;
    }
    if (rollbackBlockNo > 0) {
      this.rollbackBlock(rollbackBlockNo);
    }
    this.addBlocks(blocks);
    for (Block block : blocks) {
      AbstractDb.txProvider.confirmTx(block.getBlockNo(), block.getTxHashes());
    }
    this.lastBlock = blocks.get(blocks.size() - 1);
    return blocks.size();
  }
Ejemplo n.º 7
0
  /*
   * if result is true, means the block is in main chain, if result is false, means the block is single
   * or orphan.
   * */
  public boolean relayedBlock(Block block) throws VerificationException {
    Block prev = AbstractDb.blockProvider.getBlock(block.getBlockPrev());

    if (prev == null) {

      log.debug("prev block is null, prev hash is : " + Utils.hashToString(block.getBlockPrev()));
      //            DDLogDebug(@"%@:%d relayed orphan block %@, previous %@, last block is %@,
      // height %d", peer.host, peer.port,
      //                    block.blockHash, block.prevBlock, self.lastBlock.blockHash,
      // self.lastBlock.height);

      // ignore orphans older than one week ago
      //            if (block.blockTime - NSTimeIntervalSince1970 < [NSDate
      // timeIntervalSinceReferenceDate] - ONE_WEEK) return;

      this.singleBlocks.put(block.getBlockPrev(), block);
      return false;
      //            // call get blocks, unless we already did with the previous block, or we're
      // still downloading the chain
      //            if (self.lastBlock.height >= peer.lastBlock && ![self.lastOrphan.blockHash
      // isEqual:block.prevBlock]) {
      //                DDLogDebug(@"%@:%d calling getblocks", peer.host, peer.port);
      //                [peer sendGetBlocksMessageWithLocators:[self blockLocatorArray]
      // andHashStop:nil];
      //            }
    }

    block.setBlockNo(prev.getBlockNo() + 1);
    // TODO
    //        int transitionTime = 0;
    //        // hit a difficulty transition, find previous transition time
    //        if ((block.getBlockNo() % BitherjSettings.BLOCK_DIFFICULTY_INTERVAL) == 0) {
    //            Block b = block;
    //            for (int i = 0; b != null && i < BitherjSettings.BLOCK_DIFFICULTY_INTERVAL; i++) {
    //                b = DbHelper.blockProvider.getBlock(b.getBlockPrev());
    //            }
    //            transitionTime = b.getBlockTime();
    //        }

    // verify block difficulty
    block.verifyDifficultyFromPreviousBlock(prev);
    //        if (!block.verifyDifficultyFromPreviousBlock(prev)) {
    //            callback(block, NO);
    //            return;
    //        }

    boolean result = false;
    if (Arrays.equals(block.getBlockPrev(), this.lastBlock.getBlockHash())) {
      this.extendMainChain(block);
      result = true;
    } else if (this.inMainChain(block)) {
      result = true;
    } else {
      if (block.getBlockNo() <= BitherjSettings.BITCOIN_REFERENCE_BLOCK_HEIGHT) {
        log.debug("block is too old");
        return false;
      }
      if (block.getBlockNo() <= this.lastBlock.getBlockNo()) {
        this.addOrphan(block);
        log.debug("block is orphan");
        return false;
      }

      if (block.getBlockNo() > this.lastBlock.getBlockNo()) {
        Block b = this.getSameParent(block, this.lastBlock);
        this.rollbackBlock(b.getBlockNo());
        log.debug("roll back block from" + b.getBlockNo());
      }
    }
    if (!result) log.debug("block is not in main chain");
    return result;
  }