Browse Source

added block timestamp too-soon check and relaxed PoS for too-old blocks

pull/67/head
catbref 6 years ago
parent
commit
3045841151
  1. 34
      src/qora/block/Block.java
  2. 7
      src/qora/block/BlockChain.java

34
src/qora/block/Block.java

@ -74,6 +74,7 @@ public class Block {
TIMESTAMP_OLDER_THAN_PARENT(20), TIMESTAMP_OLDER_THAN_PARENT(20),
TIMESTAMP_IN_FUTURE(21), TIMESTAMP_IN_FUTURE(21),
TIMESTAMP_MS_INCORRECT(22), TIMESTAMP_MS_INCORRECT(22),
TIMESTAMP_TOO_SOON(23),
VERSION_INCORRECT(30), VERSION_INCORRECT(30),
FEATURE_NOT_YET_RELEASED(31), FEATURE_NOT_YET_RELEASED(31),
GENERATING_BALANCE_INCORRECT(40), GENERATING_BALANCE_INCORRECT(40),
@ -207,21 +208,35 @@ public class Block {
} }
long timestamp = parentBlock.calcNextBlockTimestamp(version, generatorSignature, generator); long timestamp = parentBlock.calcNextBlockTimestamp(version, generatorSignature, generator);
long maximumTimestamp = parentBlock.getBlockData().getTimestamp() + BlockChain.getInstance().getMaxBlockTime();
if (timestamp > maximumTimestamp)
timestamp = maximumTimestamp;
int transactionCount = 0; int transactionCount = 0;
byte[] transactionsSignature = null; byte[] transactionsSignature = null;
int height = parentBlockData.getHeight() + 1; int height = parentBlockData.getHeight() + 1;
this.executeATs(); this.transactions = new ArrayList<Transaction>();
int atCount = this.ourAtStates.size(); int atCount = 0;
BigDecimal atFees = this.ourAtFees; BigDecimal atFees = BigDecimal.ZERO.setScale(8);
BigDecimal totalFees = atFees; BigDecimal totalFees = atFees;
// This instance used for AT processing
this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance, this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance,
generator.getPublicKey(), generatorSignature, atCount, atFees); generator.getPublicKey(), generatorSignature, atCount, atFees);
this.transactions = new ArrayList<Transaction>(); // Requires this.blockData and this.transactions, sets this.ourAtStates and this.ourAtFees
this.executeATs();
atCount = this.ourAtStates.size();
this.atStates = this.ourAtStates; this.atStates = this.ourAtStates;
atFees = this.ourAtFees;
totalFees = atFees;
// Rebuild blockData using post-AT-execute data
this.blockData = new BlockData(version, reference, transactionCount, totalFees, transactionsSignature, height, timestamp, generatingBalance,
generator.getPublicKey(), generatorSignature, atCount, atFees);
} }
// Getters/setters // Getters/setters
@ -681,6 +696,10 @@ public class Block {
if (this.blockData.getTimestamp() % 1000 != parentBlockData.getTimestamp() % 1000) if (this.blockData.getTimestamp() % 1000 != parentBlockData.getTimestamp() % 1000)
return ValidationResult.TIMESTAMP_MS_INCORRECT; return ValidationResult.TIMESTAMP_MS_INCORRECT;
// Too early to forge block?
if (this.blockData.getTimestamp() < parentBlock.getBlockData().getTimestamp() + BlockChain.getInstance().getMinBlockTime())
return ValidationResult.TIMESTAMP_TOO_SOON;
// Check block version // Check block version
if (this.blockData.getVersion() != parentBlock.getNextBlockVersion()) if (this.blockData.getVersion() != parentBlock.getNextBlockVersion())
return ValidationResult.VERSION_INCORRECT; return ValidationResult.VERSION_INCORRECT;
@ -691,7 +710,9 @@ public class Block {
if (this.blockData.getGeneratingBalance().compareTo(parentBlock.calcNextBlockGeneratingBalance()) != 0) if (this.blockData.getGeneratingBalance().compareTo(parentBlock.calcNextBlockGeneratingBalance()) != 0)
return ValidationResult.GENERATING_BALANCE_INCORRECT; return ValidationResult.GENERATING_BALANCE_INCORRECT;
// Check generator is allowed to forge this block at this time // After maximum block period, then generator checks are relaxed
if (this.blockData.getTimestamp() < parentBlock.getBlockData().getTimestamp() + BlockChain.getInstance().getMaxBlockTime()) {
// Check generator is allowed to forge this block
BigInteger hashValue = this.calcBlockHash(); BigInteger hashValue = this.calcBlockHash();
BigInteger target = parentBlock.calcGeneratorsTarget(this.generator); BigInteger target = parentBlock.calcGeneratorsTarget(this.generator);
@ -708,6 +729,7 @@ public class Block {
// Each second elapsed allows generator to test a new "target" window against hashValue // Each second elapsed allows generator to test a new "target" window against hashValue
if (hashValue.compareTo(lowerTarget) < 0) if (hashValue.compareTo(lowerTarget) < 0)
return ValidationResult.GENERATOR_NOT_ACCEPTED; return ValidationResult.GENERATOR_NOT_ACCEPTED;
}
// CIYAM ATs // CIYAM ATs
if (this.blockData.getATCount() != 0) { if (this.blockData.getATCount() != 0) {
@ -720,6 +742,8 @@ public class Block {
} else { } else {
// Generate local AT states for comparison // Generate local AT states for comparison
this.executeATs(); this.executeATs();
// XXX do we need to revalidate signatures if transactions list has changed?
} }
// Check locally generated AT states against ones received from elsewhere // Check locally generated AT states against ones received from elsewhere

7
src/qora/block/BlockChain.java

@ -6,7 +6,6 @@ import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -157,9 +156,9 @@ public class BlockChain {
long maxBytesPerUnitFee = (Long) Settings.getTypedJson(json, "maxBytesPerUnitFee", Long.class); long maxBytesPerUnitFee = (Long) Settings.getTypedJson(json, "maxBytesPerUnitFee", Long.class);
BigDecimal maxBalance = Settings.getJsonBigDecimal(json, "coinSupply"); BigDecimal maxBalance = Settings.getJsonBigDecimal(json, "coinSupply");
int blockDifficultyInterval = ((Long) Settings.getTypedJson(json, "blockDifficultyInterval", Long.class)).intValue(); int blockDifficultyInterval = ((Long) Settings.getTypedJson(json, "blockDifficultyInterval", Long.class)).intValue();
long minBlockTime = (Long) Settings.getTypedJson(json, "minBlockTime", Long.class); long minBlockTime = 1000L * (Long) Settings.getTypedJson(json, "minBlockTime", Long.class); // config entry in seconds
long maxBlockTime = (Long) Settings.getTypedJson(json, "maxBlockTime", Long.class); long maxBlockTime = 1000L * (Long) Settings.getTypedJson(json, "maxBlockTime", Long.class); // config entry in seconds
long blockTimestampMargin = (Long) Settings.getTypedJson(json, "blockTimestampMargin", Long.class); long blockTimestampMargin = (Long) Settings.getTypedJson(json, "blockTimestampMargin", Long.class); // config entry in milliseconds
// blockchain feature triggers // blockchain feature triggers
Map<String, Map<FeatureValueType, Long>> featureTriggers = new HashMap<>(); Map<String, Map<FeatureValueType, Long>> featureTriggers = new HashMap<>();

Loading…
Cancel
Save