예제 #1
0
  private static void verifyDifficulty(
      StoredBlock prevBlock, Block added, BigInteger calcDiff, NetworkParameters params) {
    if (calcDiff.compareTo(params.getMaxTarget()) > 0) {
      log.info("Difficulty hit proof of work limit: {}", calcDiff.toString(16));
      calcDiff = params.getMaxTarget();
    }

    int accuracyBytes = (int) (added.getDifficultyTarget() >>> 24) - 3;
    final BigInteger receivedDifficulty = added.getDifficultyTargetAsInteger();

    // The calculated difficulty is to a higher precision than received, so reduce here.
    final BigInteger mask = BigInteger.valueOf(0xFFFFFFL).shiftLeft(accuracyBytes * 8);
    calcDiff = calcDiff.and(mask);

    if (CoinDefinition.TEST_NETWORK_STANDARD.equals(params.getStandardNetworkId())) {
      if (calcDiff.compareTo(receivedDifficulty) != 0) {
        throw new VerificationException(
            "Network provided difficulty bits do not match what was calculated: "
                + receivedDifficulty.toString(16)
                + " vs "
                + calcDiff.toString(16));
      }
    } else {
      final int height = prevBlock.getHeight() + 1;
      if (height <= 68589) {
        long nBitsNext = added.getDifficultyTarget();

        long calcDiffBits = (accuracyBytes + 3) << 24;
        calcDiffBits |= calcDiff.shiftRight(accuracyBytes * 8).longValue();

        final double n1 = CommonUtils.convertBitsToDouble(calcDiffBits);
        final double n2 = CommonUtils.convertBitsToDouble(nBitsNext);

        if (Math.abs(n1 - n2) > n1 * 0.2) {
          throw new VerificationException(
              "Network provided difficulty bits do not match what was calculated: "
                  + receivedDifficulty.toString(16)
                  + " vs "
                  + calcDiff.toString(16));
        }
      } else {
        if (calcDiff.compareTo(receivedDifficulty) != 0) {
          throw new VerificationException(
              "Network provided difficulty bits do not match what was calculated: "
                  + receivedDifficulty.toString(16)
                  + " vs "
                  + calcDiff.toString(16));
        }
      }
    }
  }
 /**
  * Returns the number of seconds from now until this servers next channel will expire, or zero if
  * no unexpired channels found.
  */
 public long getSecondsUntilExpiry(Sha256Hash id) {
   lock.lock();
   try {
     final Set<StoredClientChannel> setChannels = mapChannels.get(id);
     final long nowSeconds = Utils.currentTimeSeconds();
     int earliestTime = Integer.MAX_VALUE;
     for (StoredClientChannel channel : setChannels) {
       synchronized (channel) {
         if (channel.expiryTimeSeconds() > nowSeconds)
           earliestTime = Math.min(earliestTime, (int) channel.expiryTimeSeconds());
       }
     }
     return earliestTime == Integer.MAX_VALUE ? 0 : earliestTime - nowSeconds;
   } finally {
     lock.unlock();
   }
 }
예제 #3
0
  private static void kimotoGravityWellCheck(
      StoredBlock prevBlock, Block added, BlockStore store, NetworkParameters params)
      throws BlockStoreException {
    final long blocksTargetSpacing = (long) (2.5 * 60); // 2.5 minutes
    int timeDaySeconds = 60 * 60 * 24;
    long pastSecondsMin = timeDaySeconds / 40;
    long pastSecondsMax = timeDaySeconds * 7;
    long pastBlocksMin = pastSecondsMin / blocksTargetSpacing;
    long pastBlocksMax = pastSecondsMax / blocksTargetSpacing;

    StoredBlock blockReading = prevBlock;

    long pastBlocksMass = 0;
    long pastRateActualSeconds = 0;
    long pastRateTargetSeconds = 0;
    double pastRateAdjustmentRatio = 1.0f;
    BigInteger pastDifficultyAverage = BigInteger.valueOf(0);
    BigInteger pastDifficultyAveragePrev = BigInteger.valueOf(0);
    double eventHorizonDeviation;
    double eventHorizonDeviationFast;
    double eventHorizonDeviationSlow;

    if (prevBlock == null
        || prevBlock.getHeight() == 0
        || (long) prevBlock.getHeight() < pastBlocksMin) {
      verifyDifficulty(prevBlock, added, params.getMaxTarget(), params);
      return;
    }

    final Block prevHeader = prevBlock.getHeader();
    long latestBlockTime = prevHeader.getTimeSeconds();

    for (int i = 1; blockReading.getHeight() > 0; i++) {
      if (pastBlocksMax > 0 && i > pastBlocksMax) {
        break;
      }
      pastBlocksMass++;

      if (i == 1) {
        pastDifficultyAverage = blockReading.getHeader().getDifficultyTargetAsInteger();
      } else {
        pastDifficultyAverage =
            (blockReading
                    .getHeader()
                    .getDifficultyTargetAsInteger()
                    .subtract(pastDifficultyAveragePrev))
                .divide(BigInteger.valueOf(i))
                .add(pastDifficultyAveragePrev);
      }
      pastDifficultyAveragePrev = pastDifficultyAverage;

      if (blockReading.getHeight() > 646120
          && latestBlockTime < blockReading.getHeader().getTimeSeconds()) {
        // eliminates the ability to go back in time
        latestBlockTime = blockReading.getHeader().getTimeSeconds();
      }

      pastRateActualSeconds =
          prevHeader.getTimeSeconds() - blockReading.getHeader().getTimeSeconds();
      pastRateTargetSeconds = blocksTargetSpacing * pastBlocksMass;
      if (blockReading.getHeight() > 646120) {
        // this should slow down the upward difficulty change
        if (pastRateActualSeconds < 5) {
          pastRateActualSeconds = 5;
        }
      } else {
        if (pastRateActualSeconds < 0) {
          pastRateActualSeconds = 0;
        }
      }
      if (pastRateActualSeconds != 0 && pastRateTargetSeconds != 0) {
        pastRateAdjustmentRatio = (double) pastRateTargetSeconds / pastRateActualSeconds;
      }
      eventHorizonDeviation = 1 + 0.7084 * Math.pow((double) pastBlocksMass / 28.2d, -1.228);
      eventHorizonDeviationFast = eventHorizonDeviation;
      eventHorizonDeviationSlow = 1 / eventHorizonDeviation;

      if (pastBlocksMass >= pastBlocksMin) {
        if (pastRateAdjustmentRatio <= eventHorizonDeviationSlow
            || pastRateAdjustmentRatio >= eventHorizonDeviationFast) {
          break;
        }
      }
      blockReading = store.get(blockReading.getHeader().getPrevBlockHash());
      if (blockReading == null) {
        return;
      }
    }

    BigInteger newDifficulty = pastDifficultyAverage;
    if (pastRateActualSeconds != 0 && pastRateTargetSeconds != 0) {
      newDifficulty = newDifficulty.multiply(BigInteger.valueOf(pastRateActualSeconds));
      newDifficulty = newDifficulty.divide(BigInteger.valueOf(pastRateTargetSeconds));
    }

    if (newDifficulty.compareTo(params.getMaxTarget()) > 0) {
      log.info("Difficulty hit proof of work limit: {}", newDifficulty.toString(16));
      newDifficulty = params.getMaxTarget();
    }

    verifyDifficulty(prevBlock, added, newDifficulty, params);
  }