mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-21 14:04:16 +01:00
Block: add new constructors to reduce mutability
* New constructors and static factory methods * Update code to use the new constructors * Remove `public` from `@VisibleForTesting` setters where possible
This commit is contained in:
parent
734993db68
commit
16ac8751bb
8 changed files with 61 additions and 54 deletions
|
@ -51,6 +51,7 @@ import java.util.Date;
|
|||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.bitcoinj.base.Coin.FIFTY_COINS;
|
||||
import static org.bitcoinj.base.Sha256Hash.hashTwice;
|
||||
|
@ -178,13 +179,32 @@ public class Block extends BaseMessage {
|
|||
return transactions;
|
||||
}
|
||||
|
||||
/** Special case constructor, used for the genesis node, cloneAsHeader and unit tests. */
|
||||
/** Special case constructor, used for unit tests. */
|
||||
@VisibleForTesting
|
||||
Block(long setVersion) {
|
||||
// Set up a few basic things. We are not complete after this though.
|
||||
version = setVersion;
|
||||
difficultyTarget = 0x1d07fff8L;
|
||||
time = TimeUtils.currentTime().truncatedTo(ChronoUnit.SECONDS); // convert to Bitcoin time
|
||||
prevBlockHash = Sha256Hash.ZERO_HASH;
|
||||
this(setVersion,
|
||||
TimeUtils.currentTime().truncatedTo(ChronoUnit.SECONDS), // convert to Bitcoin time)
|
||||
0x1d07fff8L,
|
||||
0,
|
||||
Collections.emptyList());
|
||||
}
|
||||
|
||||
// For unit-test genesis blocks
|
||||
@VisibleForTesting
|
||||
Block(long setVersion, Instant time, long difficultyTarget, List<Transaction> transactions) {
|
||||
this(setVersion, time, difficultyTarget, 0, transactions);
|
||||
// Solve for nonce?
|
||||
}
|
||||
|
||||
// For genesis blocks (and also unit tests)
|
||||
Block(long setVersion, Instant time, long difficultyTarget, long nonce, List<Transaction> transactions) {
|
||||
this.version = setVersion;
|
||||
this.time = time;
|
||||
this.difficultyTarget = difficultyTarget;
|
||||
this.nonce = nonce;
|
||||
this.prevBlockHash = Sha256Hash.ZERO_HASH;
|
||||
this.transactions = new ArrayList<>(Objects.requireNonNull(transactions));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -229,12 +249,18 @@ public class Block extends BaseMessage {
|
|||
transactions);
|
||||
}
|
||||
|
||||
public static Block createGenesis() {
|
||||
Block genesisBlock = new Block(BLOCK_VERSION_GENESIS);
|
||||
public static Block createGenesis(Instant time, long difficultyTarget) {
|
||||
return new Block(BLOCK_VERSION_GENESIS, time, difficultyTarget, genesisTransactions());
|
||||
}
|
||||
|
||||
public static Block createGenesis(Instant time, long difficultyTarget, long nonce) {
|
||||
return new Block(BLOCK_VERSION_GENESIS, time, difficultyTarget, nonce, genesisTransactions());
|
||||
}
|
||||
|
||||
private static List<Transaction> genesisTransactions() {
|
||||
Transaction tx = Transaction.coinbase(genesisTxInputScriptBytes);
|
||||
tx.addOutput(new TransactionOutput(tx, FIFTY_COINS, genesisTxScriptPubKeyBytes));
|
||||
genesisBlock.addTransaction(tx);
|
||||
return genesisBlock;
|
||||
return Collections.singletonList(tx);
|
||||
}
|
||||
|
||||
// A script containing the difficulty bits and the following message:
|
||||
|
@ -367,14 +393,8 @@ public class Block extends BaseMessage {
|
|||
* @return new, header-only {@code Block}
|
||||
*/
|
||||
public Block cloneAsHeader() {
|
||||
Block block = new Block(version);
|
||||
block.difficultyTarget = difficultyTarget;
|
||||
block.time = time;
|
||||
block.nonce = nonce;
|
||||
block.prevBlockHash = prevBlockHash;
|
||||
block.merkleRoot = getMerkleRoot();
|
||||
Block block = new Block(version, prevBlockHash, getMerkleRoot(), time, difficultyTarget, nonce, null);
|
||||
block.hash = getHash();
|
||||
block.transactions = null;
|
||||
return block;
|
||||
}
|
||||
|
||||
|
@ -729,7 +749,7 @@ public class Block extends BaseMessage {
|
|||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setTime(Instant time) {
|
||||
void setTime(Instant time) {
|
||||
unCacheHeader();
|
||||
this.time = time.truncatedTo(ChronoUnit.SECONDS); // convert to Bitcoin time
|
||||
this.hash = null;
|
||||
|
@ -750,7 +770,7 @@ public class Block extends BaseMessage {
|
|||
|
||||
/** Sets the difficulty target in compact form. */
|
||||
@VisibleForTesting
|
||||
public void setDifficultyTarget(long compactForm) {
|
||||
void setDifficultyTarget(long compactForm) {
|
||||
unCacheHeader();
|
||||
this.difficultyTarget = compactForm;
|
||||
this.hash = null;
|
||||
|
@ -766,7 +786,7 @@ public class Block extends BaseMessage {
|
|||
|
||||
/** Sets the nonce and clears any cached data. */
|
||||
@VisibleForTesting
|
||||
public void setNonce(long nonce) {
|
||||
void setNonce(long nonce) {
|
||||
unCacheHeader();
|
||||
this.nonce = nonce;
|
||||
this.hash = null;
|
||||
|
|
|
@ -134,10 +134,7 @@ public class MainNetParams extends BitcoinNetworkParams {
|
|||
public Block getGenesisBlock() {
|
||||
synchronized (GENESIS_HASH) {
|
||||
if (genesisBlock == null) {
|
||||
genesisBlock = Block.createGenesis();
|
||||
genesisBlock.setDifficultyTarget(Block.STANDARD_MAX_DIFFICULTY_TARGET);
|
||||
genesisBlock.setTime(GENESIS_TIME);
|
||||
genesisBlock.setNonce(GENESIS_NONCE);
|
||||
genesisBlock = Block.createGenesis(GENESIS_TIME, Block.STANDARD_MAX_DIFFICULTY_TARGET, GENESIS_NONCE);
|
||||
checkState(genesisBlock.getHash().equals(GENESIS_HASH), () -> "invalid genesis hash");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,10 +82,7 @@ public class RegTestParams extends BitcoinNetworkParams {
|
|||
public Block getGenesisBlock() {
|
||||
synchronized (GENESIS_HASH) {
|
||||
if (genesisBlock == null) {
|
||||
genesisBlock = Block.createGenesis();
|
||||
genesisBlock.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
|
||||
genesisBlock.setTime(GENESIS_TIME);
|
||||
genesisBlock.setNonce(GENESIS_NONCE);
|
||||
genesisBlock = Block.createGenesis(GENESIS_TIME, Block.EASIEST_DIFFICULTY_TARGET, GENESIS_NONCE);
|
||||
checkState(genesisBlock.getHash().equals(GENESIS_HASH), () ->
|
||||
"invalid genesis hash");
|
||||
}
|
||||
|
|
|
@ -79,10 +79,7 @@ public class SigNetParams extends BitcoinNetworkParams {
|
|||
public Block getGenesisBlock() {
|
||||
synchronized (GENESIS_HASH) {
|
||||
if (genesisBlock == null) {
|
||||
genesisBlock = Block.createGenesis();
|
||||
genesisBlock.setDifficultyTarget(GENESIS_DIFFICULTY);
|
||||
genesisBlock.setTime(GENESIS_TIME);
|
||||
genesisBlock.setNonce(GENESIS_NONCE);
|
||||
genesisBlock = Block.createGenesis(GENESIS_TIME, GENESIS_DIFFICULTY, GENESIS_NONCE);
|
||||
checkState(genesisBlock.getHash().equals(GENESIS_HASH), () ->
|
||||
"invalid genesis hash");
|
||||
}
|
||||
|
|
|
@ -88,10 +88,7 @@ public class TestNet3Params extends BitcoinNetworkParams {
|
|||
public Block getGenesisBlock() {
|
||||
synchronized (GENESIS_HASH) {
|
||||
if (genesisBlock == null) {
|
||||
genesisBlock = Block.createGenesis();
|
||||
genesisBlock.setDifficultyTarget(Block.STANDARD_MAX_DIFFICULTY_TARGET);
|
||||
genesisBlock.setTime(GENESIS_TIME);
|
||||
genesisBlock.setNonce(GENESIS_NONCE);
|
||||
genesisBlock = Block.createGenesis(GENESIS_TIME, Block.STANDARD_MAX_DIFFICULTY_TARGET, GENESIS_NONCE);
|
||||
checkState(genesisBlock.getHash().equals(GENESIS_HASH), () ->
|
||||
"invalid genesis hash");
|
||||
}
|
||||
|
|
|
@ -73,9 +73,7 @@ public class UnitTestParams extends BitcoinNetworkParams {
|
|||
public Block getGenesisBlock() {
|
||||
synchronized (this) {
|
||||
if (genesisBlock == null) {
|
||||
genesisBlock = Block.createGenesis();
|
||||
genesisBlock.setDifficultyTarget(Block.EASIEST_DIFFICULTY_TARGET);
|
||||
genesisBlock.setTime(TimeUtils.currentTime());
|
||||
genesisBlock = Block.createGenesis(TimeUtils.currentTime(), Block.EASIEST_DIFFICULTY_TARGET);
|
||||
}
|
||||
}
|
||||
return genesisBlock;
|
||||
|
|
|
@ -414,24 +414,26 @@ public class BlockChainTest {
|
|||
|
||||
// Some blocks from the test net.
|
||||
private static Block getBlock2() throws Exception {
|
||||
Block b2 = new Block(Block.BLOCK_VERSION_GENESIS);
|
||||
b2.setMerkleRoot(Sha256Hash.wrap("20222eb90f5895556926c112bb5aa0df4ab5abc3107e21a6950aec3b2e3541e2"));
|
||||
b2.setNonce(875942400L);
|
||||
b2.setTime(Instant.ofEpochSecond(1296688946L));
|
||||
b2.setDifficultyTarget(0x1d00ffff);
|
||||
b2.setPrevBlockHash(Sha256Hash.wrap("00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206"));
|
||||
Block b2 = new Block(Block.BLOCK_VERSION_GENESIS,
|
||||
Sha256Hash.wrap("00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206"), // prev
|
||||
Sha256Hash.wrap("20222eb90f5895556926c112bb5aa0df4ab5abc3107e21a6950aec3b2e3541e2"), // merkle
|
||||
Instant.ofEpochSecond(1296688946L),
|
||||
0x1d00ffff,
|
||||
875942400L,
|
||||
null);
|
||||
assertEquals("000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820", b2.getHashAsString());
|
||||
Block.verifyHeader(b2);
|
||||
return b2;
|
||||
}
|
||||
|
||||
private static Block getBlock1() throws Exception {
|
||||
Block b1 = new Block(Block.BLOCK_VERSION_GENESIS);
|
||||
b1.setMerkleRoot(Sha256Hash.wrap("f0315ffc38709d70ad5647e22048358dd3745f3ce3874223c80a7c92fab0c8ba"));
|
||||
b1.setNonce(1924588547);
|
||||
b1.setTime(Instant.ofEpochSecond(1296688928));
|
||||
b1.setDifficultyTarget(0x1d00ffff);
|
||||
b1.setPrevBlockHash(Sha256Hash.wrap("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"));
|
||||
Block b1 = new Block(Block.BLOCK_VERSION_GENESIS,
|
||||
Sha256Hash.wrap("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"), // prev
|
||||
Sha256Hash.wrap("f0315ffc38709d70ad5647e22048358dd3745f3ce3874223c80a7c92fab0c8ba"), // merkle
|
||||
Instant.ofEpochSecond(1296688928),
|
||||
0x1d00ffff,
|
||||
1924588547,
|
||||
null);
|
||||
assertEquals("00000000b873e79784647a6c82962c70d228557d24a747ea4d1b8bbe878e1206", b1.getHashAsString());
|
||||
Block.verifyHeader(b1);
|
||||
return b1;
|
||||
|
|
|
@ -336,10 +336,9 @@ public class BlockTest {
|
|||
|
||||
@Test
|
||||
public void testGenesisBlock() {
|
||||
Block genesisBlock = Block.createGenesis();
|
||||
genesisBlock.setDifficultyTarget(0x1d00ffffL);
|
||||
genesisBlock.setTime(Instant.ofEpochSecond(1231006505L));
|
||||
genesisBlock.setNonce(2083236893);
|
||||
Block genesisBlock = Block.createGenesis(Instant.ofEpochSecond(1231006505L),
|
||||
0x1d00ffffL,
|
||||
2083236893);
|
||||
assertEquals(Sha256Hash.wrap("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"), genesisBlock.getHash());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue