private void unCacheHeader() { maybeParseHeader(); headerBytesValid = false; if (!transactionBytesValid) bytes = null; hash = null; checksum = null; }
private void checkTimestamp() throws VerificationException { maybeParseHeader(); // Allow injection of a fake clock to allow unit testing. long currentTime = fakeClock != 0 ? fakeClock : System.currentTimeMillis() / 1000; if (time > currentTime + ALLOWED_TIME_DRIFT) throw new VerificationException("Block too far in future"); }
/** * Returns the difficulty target as a 320 bit value that can be compared to a scrypt hash. Inside * a block the target is represented using a compact form. If this form decodes to a value that is * out of bounds, an exception is thrown. */ public BigInteger getDifficultyTargetAsInteger() throws VerificationException { maybeParseHeader(); BigInteger target = Utils.decodeCompactBits(difficultyTarget); if (target.compareTo(BigInteger.ZERO) <= 0 || target.compareTo(params.proofOfWorkLimit) > 0) throw new VerificationException( "Difficulty target is bad: " + target.toString() + " or " + difficultyTarget); return target; }
/** * In lazy parsing mode access to getters and setters may throw an unchecked LazyParseException. * If guaranteed safe access is required this method will force parsing to occur immediately thus * ensuring LazyParseExeption will never be thrown from this Message. If the Message contains * child messages (e.g. a Block containing Transaction messages) this will not force child * messages to parse. * * <p>This method ensures parsing of headers only. * * @throws ProtocolException */ public void ensureParsedHeader() throws ProtocolException { try { maybeParseHeader(); } catch (LazyParseException e) { if (e.getCause() instanceof ProtocolException) throw (ProtocolException) e.getCause(); throw new ProtocolException(e); } }
/** Returns the merkle root in big endian form, calculating it from transactions if necessary. */ public Sha256Hash getMerkleRoot() { maybeParseHeader(); if (merkleRoot == null) { // TODO check if this is really necessary. unCacheHeader(); merkleRoot = calculateMerkleRoot(); } return merkleRoot; }
/** * Checks the block data to ensure it follows the rules laid out in the network parameters. * Specifically, throws an exception if the proof of work is invalid, or if the timestamp is too * far from what it should be. This is <b>not</b> everything that is required for a block to be * valid, only what is checkable independent of the chain and without a transaction index. * * @throws VerificationException */ public void verifyHeader() throws VerificationException { // Prove that this block is OK. It might seem that we can just ignore most of these checks given // that the // network is also verifying the blocks, but we cannot as it'd open us to a variety of obscure // attacks. // // Firstly we need to ensure this block does in fact represent real work done. If the difficulty // is high // enough, it's probably been done by the network. maybeParseHeader(); checkProofOfWork(true); checkTimestamp(); }
/** * Finds a value of nonce that makes the blocks hash lower than the difficulty target. This is * called mining, but solve() is far too slow to do real mining with. It exists only for unit * testing purposes and is not a part of the public API. * * <p>This can loop forever if a solution cannot be found solely by incrementing nonce. It doesn't * change extraNonce. */ void solve() { maybeParseHeader(); while (true) { try { // Is our proof of work valid yet? if (checkProofOfWork(false)) return; // No, so increment the nonce and try again. setNonce(getNonce() + 1); } catch (VerificationException e) { throw new RuntimeException(e); // Cannot happen. } } }
/** Returns a copy of the block, but without any transactions. */ public Block cloneAsHeader() { maybeParseHeader(); Block block = new Block(params); block.nonce = nonce; block.prevBlockHash = prevBlockHash.duplicate(); block.merkleRoot = getMerkleRoot().duplicate(); block.version = version; block.time = time; block.difficultyTarget = difficultyTarget; block.transactions = null; block.hash = getHash().duplicate(); return block; }
// default for testing void writeHeader(OutputStream stream) throws IOException { // try for cached write first if (headerBytesValid && bytes != null && bytes.length >= offset + HEADER_SIZE) { stream.write(bytes, offset, HEADER_SIZE); return; } // fall back to manual write maybeParseHeader(); Utils.uint32ToByteStreamLE(version, stream); stream.write(Utils.reverseBytes(prevBlockHash.getBytes())); stream.write(Utils.reverseBytes(getMerkleRoot().getBytes())); Utils.uint32ToByteStreamLE(time, stream); Utils.uint32ToByteStreamLE(difficultyTarget, stream); Utils.uint32ToByteStreamLE(nonce, stream); }
/** * Returns the nonce, an arbitrary value that exists only to make the hash of the block header * fall below the difficulty target. */ public long getNonce() { maybeParseHeader(); return nonce; }
/** * Returns the difficulty of the proof of work that this block should meet encoded <b>in compact * form</b>. The {@link BlockChain} verifies that this is not too easy by looking at the length of * the chain when the block is added. To find the actual value the hash should be compared * against, use {@link net.usecredits.credits.core.Block#getDifficultyTargetAsInteger()}. Note * that this is <b>not</b> the same as the difficulty value reported by the Litecoin * "getdifficulty" RPC that you may see on various block explorers. That number is the result of * applying a formula to the underlying difficulty to normalize the minimum to 1. Calculating the * difficulty that way is currently unsupported. */ public long getDifficultyTarget() { maybeParseHeader(); return difficultyTarget; }
/** * Returns the time at which the block was solved and broadcast, according to the clock of the * solving node. This is measured in seconds since the UNIX epoch (midnight Jan 1st 1970). */ public long getTimeSeconds() { maybeParseHeader(); return time; }
/** Returns the hash of the previous block in the chain, as defined by the block header. */ public Sha256Hash getPrevBlockHash() { maybeParseHeader(); return prevBlockHash; }
/** Returns the version of the block data structure as defined by the Litecoin protocol. */ public long getVersion() { maybeParseHeader(); return version; }