forked from Qortal/qortal
added block timestamp too-soon check and relaxed PoS for too-old blocks
This commit is contained in:
parent
f50b53a407
commit
3045841151
@ -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,23 +710,26 @@ 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
|
||||||
BigInteger hashValue = this.calcBlockHash();
|
if (this.blockData.getTimestamp() < parentBlock.getBlockData().getTimestamp() + BlockChain.getInstance().getMaxBlockTime()) {
|
||||||
BigInteger target = parentBlock.calcGeneratorsTarget(this.generator);
|
// Check generator is allowed to forge this block
|
||||||
|
BigInteger hashValue = this.calcBlockHash();
|
||||||
|
BigInteger target = parentBlock.calcGeneratorsTarget(this.generator);
|
||||||
|
|
||||||
// Multiply target by guesses
|
// Multiply target by guesses
|
||||||
long guesses = (this.blockData.getTimestamp() - parentBlockData.getTimestamp()) / 1000;
|
long guesses = (this.blockData.getTimestamp() - parentBlockData.getTimestamp()) / 1000;
|
||||||
BigInteger lowerTarget = target.multiply(BigInteger.valueOf(guesses - 1));
|
BigInteger lowerTarget = target.multiply(BigInteger.valueOf(guesses - 1));
|
||||||
target = target.multiply(BigInteger.valueOf(guesses));
|
target = target.multiply(BigInteger.valueOf(guesses));
|
||||||
|
|
||||||
// Generator's target must exceed block's hashValue threshold
|
// Generator's target must exceed block's hashValue threshold
|
||||||
if (hashValue.compareTo(target) >= 0)
|
if (hashValue.compareTo(target) >= 0)
|
||||||
return ValidationResult.GENERATOR_NOT_ACCEPTED;
|
return ValidationResult.GENERATOR_NOT_ACCEPTED;
|
||||||
|
|
||||||
// Odd gen1 comment: "CHECK IF FIRST BLOCK OF USER"
|
// Odd gen1 comment: "CHECK IF FIRST BLOCK OF USER"
|
||||||
// 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
|
||||||
|
@ -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…
x
Reference in New Issue
Block a user