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
 private void forkMainChain(Block forkStartBlock, Block lastBlock) {
   Block b = this.lastBlock;
   Block next = lastBlock;
   while (!Arrays.equals(b.getBlockHash(), forkStartBlock.getBlockHash())) {
     next = AbstractDb.blockProvider.getOrphanBlockByPrevHash(b.getBlockPrev());
     AbstractDb.blockProvider.updateBlock(b.getBlockHash(), false);
     b = AbstractDb.blockProvider.getMainChainBlock(b.getBlockPrev());
     this.lastBlock = b;
   }
   b = next;
   AbstractDb.blockProvider.updateBlock(next.getBlockHash(), true);
   this.lastBlock = next;
   while (!Arrays.equals(b.getBlockHash(), lastBlock.getBlockPrev())) {
     AbstractDb.blockProvider.updateBlock(b.getBlockHash(), true);
     this.lastBlock = b;
     b = AbstractDb.blockProvider.getOrphanBlockByPrevHash(b.getBlockHash());
   }
   lastBlock.setMain(true);
   this.addBlock(lastBlock);
   this.lastBlock = lastBlock;
 }
Ejemplo n.º 7
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();
  }