/**
  * An orphan block is one that does not connect to the chain anywhere (ie we can't find its
  * parent, therefore it's an orphan). Typically this occurs when we are downloading the chain and
  * didn't reach the head yet, and/or if a block is solved whilst we are downloading. It's possible
  * that we see a small amount of orphan blocks which chain together, this method tries walking
  * backwards through the known orphan blocks to find the bottom-most.
  *
  * @return from or one of froms parents, or null if "from" does not identify an orphan block
  */
 @Nullable
 public Block getOrphanRoot(Sha256Hash from) {
   lock.lock();
   try {
     OrphanBlock cursor = orphanBlocks.get(from);
     if (cursor == null) return null;
     OrphanBlock tmp;
     while ((tmp = orphanBlocks.get(cursor.block.getPrevBlockHash())) != null) {
       cursor = tmp;
     }
     return cursor.block;
   } finally {
     lock.unlock();
   }
 }
예제 #2
0
  @Override
  @Nullable
  public StoredBlock get(Sha256Hash hash) throws BlockStoreException {
    final MappedByteBuffer buffer = this.buffer;
    if (buffer == null) throw new BlockStoreException("Store closed");

    lock.lock();
    try {
      StoredBlock cacheHit = blockCache.get(hash);
      if (cacheHit != null) return cacheHit;
      if (notFoundCache.get(hash) != null) return null;

      // Starting from the current tip of the ring work backwards until we have either found the
      // block or
      // wrapped around.
      int cursor = getRingCursor(buffer);
      final int startingPoint = cursor;
      final int fileSize = getFileSize();
      final byte[] targetHashBytes = hash.getBytes();
      byte[] scratch = new byte[32];
      do {
        cursor -= RECORD_SIZE;
        if (cursor < FILE_PROLOGUE_BYTES) {
          // We hit the start, so wrap around.
          cursor = fileSize - RECORD_SIZE;
        }
        // Cursor is now at the start of the next record to check, so read the hash and compare it.
        buffer.position(cursor);
        buffer.get(scratch);
        if (Arrays.equals(scratch, targetHashBytes)) {
          // Found the target.
          StoredBlock storedBlock = StoredBlock.deserializeCompact(params, buffer);
          blockCache.put(hash, storedBlock);
          return storedBlock;
        }
      } while (cursor != startingPoint);
      // Not found.
      notFoundCache.put(hash, notFoundMarker);
      return null;
    } catch (ProtocolException e) {
      throw new RuntimeException(e); // Cannot happen.
    } finally {
      lock.unlock();
    }
  }