mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-07-30 03:21:23 +00:00
Make BlockStore and StoredBlock public. Move StoredBlock building into the class itself.
This commit is contained in:
@@ -72,7 +72,7 @@ public class BlockChain {
|
||||
try {
|
||||
blockStore = new MemoryBlockStore(params);
|
||||
chainHead = blockStore.getChainHead();
|
||||
LOG("chain head is: " + chainHead.header.toString());
|
||||
LOG("chain head is: " + chainHead.getHeader().toString());
|
||||
} catch (BlockStoreException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -137,13 +137,13 @@ public class BlockChain {
|
||||
} else {
|
||||
// The block connects to somewhere on the chain. Not necessarily the top of the best known chain.
|
||||
checkDifficultyTransitions(storedPrev, block);
|
||||
StoredBlock newStoredBlock = buildStoredBlock(storedPrev, block);
|
||||
StoredBlock newStoredBlock = storedPrev.build(block);
|
||||
// Store it.
|
||||
blockStore.put(newStoredBlock);
|
||||
if (storedPrev.equals(chainHead)) {
|
||||
// This block connects to the best known block, it is a normal continuation of the system.
|
||||
setChainHead(newStoredBlock);
|
||||
LOG("Received new block, chain is now " + chainHead.height + " blocks high");
|
||||
LOG("Received new block, chain is now " + chainHead.getHeight() + " blocks high");
|
||||
} else {
|
||||
// This block connects to somewhere other than the top of the chain.
|
||||
if (newStoredBlock.moreWorkThan(chainHead)) {
|
||||
@@ -172,17 +172,6 @@ public class BlockChain {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the additional fields a StoredBlock holds given the previous block in the chain and the new block.
|
||||
*/
|
||||
private StoredBlock buildStoredBlock(StoredBlock storedPrev, Block block) throws VerificationException {
|
||||
// Stored blocks track total work done in this chain, because the canonical chain is the one that represents
|
||||
// the largest amount of work done not the tallest.
|
||||
BigInteger chainWork = storedPrev.chainWork.add(block.getWork());
|
||||
int height = storedPrev.height + 1;
|
||||
return new StoredBlock(block, chainWork, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* For each block in unconnectedBlocks, see if we can now fit it on top of the chain and if so, do so.
|
||||
*/
|
||||
@@ -219,12 +208,12 @@ public class BlockChain {
|
||||
*/
|
||||
private void checkDifficultyTransitions(StoredBlock storedPrev, Block next)
|
||||
throws BlockStoreException, VerificationException {
|
||||
Block prev = storedPrev.header;
|
||||
Block prev = storedPrev.getHeader();
|
||||
// Is this supposed to be a difficulty transition point?
|
||||
if ((storedPrev.height + 1) % params.interval != 0) {
|
||||
if ((storedPrev.getHeight() + 1) % params.interval != 0) {
|
||||
// No ... so check the difficulty didn't actually change.
|
||||
if (next.getDifficultyTarget() != prev.getDifficultyTarget())
|
||||
throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.height +
|
||||
throw new VerificationException("Unexpected change in difficulty at height " + storedPrev.getHeight() +
|
||||
": " + Long.toHexString(next.getDifficultyTarget()) + " vs " +
|
||||
Long.toHexString(prev.getDifficultyTarget()));
|
||||
return;
|
||||
@@ -239,10 +228,10 @@ public class BlockChain {
|
||||
throw new VerificationException(
|
||||
"Difficulty transition point but we did not find a way back to the genesis block.");
|
||||
}
|
||||
cursor = blockStore.get(cursor.header.getPrevBlockHash());
|
||||
cursor = blockStore.get(cursor.getHeader().getPrevBlockHash());
|
||||
}
|
||||
|
||||
Block blockIntervalAgo = cursor.header;
|
||||
Block blockIntervalAgo = cursor.getHeader();
|
||||
int timespan = (int) (prev.getTime() - blockIntervalAgo.getTime());
|
||||
// Limit the adjustment step.
|
||||
if (timespan < params.targetTimespan / 4)
|
||||
|
@@ -26,7 +26,7 @@ package com.google.bitcoin.core;
|
||||
*
|
||||
* BlockStores are thread safe.
|
||||
*/
|
||||
interface BlockStore {
|
||||
public interface BlockStore {
|
||||
/**
|
||||
* Saves the given block header+extra data. The key isn't specified explicitly as it can be calculated from the
|
||||
* StoredBlock directly. Can throw if there is a problem with the underlying storage layer such as running out of
|
||||
|
@@ -20,6 +20,10 @@ package com.google.bitcoin.core;
|
||||
* Thrown when something goes wrong with storing a block. Examples: out of disk space.
|
||||
*/
|
||||
public class BlockStoreException extends Exception {
|
||||
public BlockStoreException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BlockStoreException(Throwable t) {
|
||||
super(t);
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ class MemoryBlockStore implements BlockStore {
|
||||
}
|
||||
|
||||
public synchronized void put(StoredBlock block) throws BlockStoreException {
|
||||
byte[] hash = block.header.getHash();
|
||||
byte[] hash = block.getHeader().getHash();
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
try {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(bos);
|
||||
|
@@ -304,7 +304,7 @@ public class Peer {
|
||||
// We don't do the exponential thinning here, so if we get onto a fork of the chain we will end up
|
||||
// redownloading the whole thing again.
|
||||
blockLocator.add(params.genesisBlock.getHash());
|
||||
Block topBlock = blockChain.getChainHead().header;
|
||||
Block topBlock = blockChain.getChainHead().getHeader();
|
||||
if (!topBlock.equals(params.genesisBlock))
|
||||
blockLocator.add(0, topBlock.getHash());
|
||||
GetBlocksMessage message = new GetBlocksMessage(params, blockLocator, toHash);
|
||||
|
@@ -28,35 +28,46 @@ import java.math.BigInteger;
|
||||
*
|
||||
* StoredBlocks are put inside a {@link BlockStore} which saves them to memory or disk.
|
||||
*/
|
||||
class StoredBlock implements Serializable {
|
||||
public class StoredBlock implements Serializable {
|
||||
private static final long serialVersionUID = -6097565241243701771L;
|
||||
|
||||
/**
|
||||
* The block header this object wraps. The referenced block object must not have any transactions in it.
|
||||
*/
|
||||
Block header;
|
||||
private Block header;
|
||||
private BigInteger chainWork;
|
||||
private int height;
|
||||
|
||||
/**
|
||||
* The total sum of work done in this block, and all the blocks below it in the chain. Work is a measure of how
|
||||
* many tries are needed to solve a block. If the target is set to cover 10% of the total hash value space,
|
||||
* then the work represented by a block is 10.
|
||||
*/
|
||||
BigInteger chainWork;
|
||||
|
||||
/**
|
||||
* Position in the chain for this block. The genesis block has a height of zero.
|
||||
*/
|
||||
int height;
|
||||
|
||||
StoredBlock(Block header, BigInteger chainWork, int height) {
|
||||
public StoredBlock(Block header, BigInteger chainWork, int height) {
|
||||
assert header.transactions == null : "Should not have transactions in a block header object";
|
||||
this.header = header;
|
||||
this.chainWork = chainWork;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The block header this object wraps. The referenced block object must not have any transactions in it.
|
||||
*/
|
||||
public Block getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* The total sum of work done in this block, and all the blocks below it in the chain. Work is a measure of how
|
||||
* many tries are needed to solve a block. If the target is set to cover 10% of the total hash value space,
|
||||
* then the work represented by a block is 10.
|
||||
*/
|
||||
public BigInteger getChainWork() {
|
||||
return chainWork;
|
||||
}
|
||||
|
||||
/**
|
||||
* Position in the chain for this block. The genesis block has a height of zero.
|
||||
*/
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
/** Returns true if this objects chainWork is higher than the others. */
|
||||
boolean moreWorkThan(StoredBlock other) {
|
||||
public boolean moreWorkThan(StoredBlock other) {
|
||||
return chainWork.compareTo(other.chainWork) > 0;
|
||||
}
|
||||
|
||||
@@ -66,4 +77,16 @@ class StoredBlock implements Serializable {
|
||||
StoredBlock o = (StoredBlock) other;
|
||||
return o.header.equals(header) && o.chainWork.equals(chainWork) && o.height == height;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new StoredBlock, calculating the additional fields by adding to the values in this block.
|
||||
*/
|
||||
public StoredBlock build(Block block) throws VerificationException {
|
||||
// Stored blocks track total work done in this chain, because the canonical chain is the one that represents
|
||||
// the largest amount of work done not the tallest.
|
||||
BigInteger chainWork = this.chainWork.add(block.getWork());
|
||||
int height = this.height + 1;
|
||||
return new StoredBlock(block, chainWork, height);
|
||||
}
|
||||
}
|
||||
|
@@ -383,8 +383,8 @@ public class Wallet implements Serializable {
|
||||
// This runs on any peer thread with the block chain synchronized. Thus we do not have to worry about it
|
||||
// being called simultaneously or repeatedly.
|
||||
LOG("Re-organize!");
|
||||
LOG("Old chain head: " + chainHead.header.toString());
|
||||
LOG("New chain head: " + newStoredBlock.header.toString());
|
||||
LOG("Old chain head: " + chainHead.getHeader().toString());
|
||||
LOG("New chain head: " + newStoredBlock.getHeader().toString());
|
||||
|
||||
// TODO: Implement me!
|
||||
// For each transaction we have to track which blocks they appeared in. Once a re-org takes place,
|
||||
|
Reference in New Issue
Block a user