mirror of
https://github.com/Qortal/qortal.git
synced 2025-03-13 19:12:33 +00:00
Minor code tidying
This commit is contained in:
parent
319bfc8d75
commit
6ba24e1820
@ -89,7 +89,7 @@ public class Block {
|
|||||||
|
|
||||||
public final int value;
|
public final int value;
|
||||||
|
|
||||||
private final static Map<Integer, ValidationResult> map = stream(ValidationResult.values()).collect(toMap(result -> result.value, result -> result));
|
private static final Map<Integer, ValidationResult> map = stream(ValidationResult.values()).collect(toMap(result -> result.value, result -> result));
|
||||||
|
|
||||||
ValidationResult(int value) {
|
ValidationResult(int value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
@ -237,7 +237,7 @@ public class Block {
|
|||||||
public Block(Repository repository, BlockData blockData, List<TransactionData> transactions, List<ATStateData> atStates) throws DataException {
|
public Block(Repository repository, BlockData blockData, List<TransactionData> transactions, List<ATStateData> atStates) throws DataException {
|
||||||
this(repository, blockData);
|
this(repository, blockData);
|
||||||
|
|
||||||
this.transactions = new ArrayList<Transaction>();
|
this.transactions = new ArrayList<>();
|
||||||
|
|
||||||
BigDecimal totalFees = BigDecimal.ZERO.setScale(8);
|
BigDecimal totalFees = BigDecimal.ZERO.setScale(8);
|
||||||
|
|
||||||
@ -327,7 +327,7 @@ public class Block {
|
|||||||
byte[] transactionsSignature = null;
|
byte[] transactionsSignature = null;
|
||||||
int height = parentBlockData.getHeight() + 1;
|
int height = parentBlockData.getHeight() + 1;
|
||||||
|
|
||||||
this.transactions = new ArrayList<Transaction>();
|
this.transactions = new ArrayList<>();
|
||||||
|
|
||||||
int atCount = 0;
|
int atCount = 0;
|
||||||
BigDecimal atFees = BigDecimal.ZERO.setScale(8);
|
BigDecimal atFees = BigDecimal.ZERO.setScale(8);
|
||||||
@ -471,7 +471,7 @@ public class Block {
|
|||||||
if (transactionsData.size() != this.blockData.getTransactionCount())
|
if (transactionsData.size() != this.blockData.getTransactionCount())
|
||||||
throw new IllegalStateException("Block's transactions from repository do not match block's transaction count");
|
throw new IllegalStateException("Block's transactions from repository do not match block's transaction count");
|
||||||
|
|
||||||
this.transactions = new ArrayList<Transaction>();
|
this.transactions = new ArrayList<>();
|
||||||
|
|
||||||
for (TransactionData transactionData : transactionsData)
|
for (TransactionData transactionData : transactionsData)
|
||||||
this.transactions.add(Transaction.fromData(this.repository, transactionData));
|
this.transactions.add(Transaction.fromData(this.repository, transactionData));
|
||||||
@ -520,7 +520,7 @@ public class Block {
|
|||||||
return this.cachedExpandedAccounts;
|
return this.cachedExpandedAccounts;
|
||||||
|
|
||||||
ConciseSet accountIndexes = BlockTransformer.decodeOnlineAccounts(this.blockData.getEncodedOnlineAccounts());
|
ConciseSet accountIndexes = BlockTransformer.decodeOnlineAccounts(this.blockData.getEncodedOnlineAccounts());
|
||||||
List<ExpandedAccount> expandedAccounts = new ArrayList<ExpandedAccount>();
|
List<ExpandedAccount> expandedAccounts = new ArrayList<>();
|
||||||
|
|
||||||
IntIterator iterator = accountIndexes.iterator();
|
IntIterator iterator = accountIndexes.iterator();
|
||||||
while (iterator.hasNext()) {
|
while (iterator.hasNext()) {
|
||||||
@ -721,14 +721,12 @@ public class Block {
|
|||||||
byte[] idealKey = calcIdealGeneratorPublicKey(parentHeight, parentBlockSignature);
|
byte[] idealKey = calcIdealGeneratorPublicKey(parentHeight, parentBlockSignature);
|
||||||
byte[] perturbedKey = calcHeightPerturbedPublicKey(parentHeight + 1, publicKey);
|
byte[] perturbedKey = calcHeightPerturbedPublicKey(parentHeight + 1, publicKey);
|
||||||
|
|
||||||
BigInteger keyDistance = MAX_DISTANCE.subtract(new BigInteger(idealKey).subtract(new BigInteger(perturbedKey)).abs());
|
return MAX_DISTANCE.subtract(new BigInteger(idealKey).subtract(new BigInteger(perturbedKey)).abs());
|
||||||
return keyDistance;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BigInteger calcBlockWeight(int parentHeight, byte[] parentBlockSignature, BlockSummaryData blockSummaryData) {
|
public static BigInteger calcBlockWeight(int parentHeight, byte[] parentBlockSignature, BlockSummaryData blockSummaryData) {
|
||||||
BigInteger keyDistance = calcKeyDistance(parentHeight, parentBlockSignature, blockSummaryData.getGeneratorPublicKey());
|
BigInteger keyDistance = calcKeyDistance(parentHeight, parentBlockSignature, blockSummaryData.getGeneratorPublicKey());
|
||||||
BigInteger weight = BigInteger.valueOf(blockSummaryData.getOnlineAccountsCount()).shiftLeft(ACCOUNTS_COUNT_SHIFT).add(keyDistance);
|
return BigInteger.valueOf(blockSummaryData.getOnlineAccountsCount()).shiftLeft(ACCOUNTS_COUNT_SHIFT).add(keyDistance);
|
||||||
return weight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BigInteger calcChainWeight(int commonBlockHeight, byte[] commonBlockSignature, List<BlockSummaryData> blockSummaries) {
|
public static BigInteger calcChainWeight(int commonBlockHeight, byte[] commonBlockSignature, List<BlockSummaryData> blockSummaries) {
|
||||||
@ -767,7 +765,7 @@ public class Block {
|
|||||||
// Use power transform on ratio to spread out smaller values for bigger effect
|
// Use power transform on ratio to spread out smaller values for bigger effect
|
||||||
double transformed = Math.pow(ratio, blockTiming.power);
|
double transformed = Math.pow(ratio, blockTiming.power);
|
||||||
|
|
||||||
long timeOffset = Double.valueOf(blockTiming.deviation * 2.0 * transformed).longValue();
|
long timeOffset = (long) (blockTiming.deviation * 2.0 * transformed);
|
||||||
|
|
||||||
return parentBlockData.getTimestamp() + blockTiming.target - blockTiming.deviation + timeOffset;
|
return parentBlockData.getTimestamp() + blockTiming.target - blockTiming.deviation + timeOffset;
|
||||||
}
|
}
|
||||||
@ -953,9 +951,109 @@ public class Block {
|
|||||||
return onlineAccountsResult;
|
return onlineAccountsResult;
|
||||||
|
|
||||||
// CIYAM ATs
|
// CIYAM ATs
|
||||||
if (this.blockData.getATCount() != 0) {
|
ValidationResult ciyamAtResult = this.areAtsValid();
|
||||||
|
if (ciyamAtResult != ValidationResult.OK)
|
||||||
|
return ciyamAtResult;
|
||||||
|
|
||||||
|
// Check transactions
|
||||||
|
ValidationResult transactionsResult = this.areTransactionsValid();
|
||||||
|
if (transactionsResult != ValidationResult.OK)
|
||||||
|
return transactionsResult;
|
||||||
|
|
||||||
|
// Block is valid
|
||||||
|
return ValidationResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns whether block's transactions are valid. */
|
||||||
|
private ValidationResult areTransactionsValid() throws DataException {
|
||||||
|
try {
|
||||||
|
// Create repository savepoint here so we can rollback to it after testing transactions
|
||||||
|
repository.setSavepoint();
|
||||||
|
|
||||||
|
for (Transaction transaction : this.getTransactions()) {
|
||||||
|
TransactionData transactionData = transaction.getTransactionData();
|
||||||
|
|
||||||
|
// GenesisTransactions are not allowed (GenesisBlock overrides isValid() to allow them)
|
||||||
|
if (transactionData.getType() == TransactionType.GENESIS || transactionData.getType() == TransactionType.ACCOUNT_FLAGS)
|
||||||
|
return ValidationResult.GENESIS_TRANSACTIONS_INVALID;
|
||||||
|
|
||||||
|
// Check timestamp and deadline
|
||||||
|
if (transactionData.getTimestamp() > this.blockData.getTimestamp()
|
||||||
|
|| transaction.getDeadline() <= this.blockData.getTimestamp())
|
||||||
|
return ValidationResult.TRANSACTION_TIMESTAMP_INVALID;
|
||||||
|
|
||||||
|
// Check transaction isn't already included in a block
|
||||||
|
if (this.repository.getTransactionRepository().isConfirmed(transactionData.getSignature()))
|
||||||
|
return ValidationResult.TRANSACTION_ALREADY_PROCESSED;
|
||||||
|
|
||||||
|
// Check transaction has correct reference, etc.
|
||||||
|
if (!transaction.hasValidReference()) {
|
||||||
|
LOGGER.debug(String.format("Error during transaction validation, tx %s: INVALID_REFERENCE", Base58.encode(transactionData.getSignature())));
|
||||||
|
return ValidationResult.TRANSACTION_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check transaction is even valid
|
||||||
|
// NOTE: in Gen1 there was an extra block height passed to DeployATTransaction.isValid
|
||||||
|
Transaction.ValidationResult validationResult = transaction.isValid();
|
||||||
|
if (validationResult != Transaction.ValidationResult.OK) {
|
||||||
|
LOGGER.debug(String.format("Error during transaction validation, tx %s: %s", Base58.encode(transactionData.getSignature()), validationResult.name()));
|
||||||
|
return ValidationResult.TRANSACTION_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check transaction can even be processed
|
||||||
|
validationResult = transaction.isProcessable();
|
||||||
|
if (validationResult != Transaction.ValidationResult.OK) {
|
||||||
|
LOGGER.debug(String.format("Error during transaction validation, tx %s: %s", Base58.encode(transactionData.getSignature()), validationResult.name()));
|
||||||
|
return ValidationResult.TRANSACTION_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process transaction to make sure other transactions validate properly
|
||||||
|
try {
|
||||||
|
// Only process transactions that don't require group-approval.
|
||||||
|
// Group-approval transactions are dealt with later.
|
||||||
|
if (transactionData.getApprovalStatus() == ApprovalStatus.NOT_REQUIRED)
|
||||||
|
transaction.process();
|
||||||
|
|
||||||
|
// Regardless of group-approval, update relevant info for creator (e.g. lastReference)
|
||||||
|
transaction.processReferencesAndFees();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error(String.format("Exception during transaction validation, tx %s", Base58.encode(transactionData.getSignature())), e);
|
||||||
|
return ValidationResult.TRANSACTION_PROCESSING_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (DataException e) {
|
||||||
|
return ValidationResult.TRANSACTION_INVALID;
|
||||||
|
} finally {
|
||||||
|
// Rollback repository changes made by test-processing transactions above
|
||||||
|
try {
|
||||||
|
this.repository.rollbackToSavepoint();
|
||||||
|
} catch (DataException e) {
|
||||||
|
/*
|
||||||
|
* Rollback failure most likely due to prior DataException, so discard this DataException. Prior DataException propagates to caller.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ValidationResult.OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether blocks' ATs are valid.
|
||||||
|
* <p>
|
||||||
|
* NOTE: will execute ATs locally if not already done.<br>
|
||||||
|
* This is so we have locally-generated AT states for comparison.
|
||||||
|
*
|
||||||
|
* @return OK, or some AT-related validation result
|
||||||
|
* @throws DataException
|
||||||
|
*/
|
||||||
|
private ValidationResult areAtsValid() throws DataException {
|
||||||
|
if (this.blockData.getATCount() == 0)
|
||||||
|
return ValidationResult.OK;
|
||||||
|
|
||||||
// Locally generated AT states should be valid so no need to re-execute them
|
// Locally generated AT states should be valid so no need to re-execute them
|
||||||
if (this.ourAtStates != this.getATStates()) {
|
if (this.ourAtStates == this.getATStates()) // Note object reference compare
|
||||||
|
return ValidationResult.OK;
|
||||||
|
|
||||||
// For old v1 CIYAM ATs we blindly accept them
|
// For old v1 CIYAM ATs we blindly accept them
|
||||||
if (this.blockData.getVersion() < 4) {
|
if (this.blockData.getVersion() < 4) {
|
||||||
this.ourAtStates = this.atStates;
|
this.ourAtStates = this.atStates;
|
||||||
@ -981,88 +1079,13 @@ public class Block {
|
|||||||
if (!ourAtState.getATAddress().equals(theirAtState.getATAddress()))
|
if (!ourAtState.getATAddress().equals(theirAtState.getATAddress()))
|
||||||
return ValidationResult.AT_STATES_MISMATCH;
|
return ValidationResult.AT_STATES_MISMATCH;
|
||||||
|
|
||||||
if (!ourAtState.getStateHash().equals(theirAtState.getStateHash()))
|
if (!Arrays.equals(ourAtState.getStateHash(), theirAtState.getStateHash()))
|
||||||
return ValidationResult.AT_STATES_MISMATCH;
|
return ValidationResult.AT_STATES_MISMATCH;
|
||||||
|
|
||||||
if (ourAtState.getFees().compareTo(theirAtState.getFees()) != 0)
|
if (ourAtState.getFees().compareTo(theirAtState.getFees()) != 0)
|
||||||
return ValidationResult.AT_STATES_MISMATCH;
|
return ValidationResult.AT_STATES_MISMATCH;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check transactions
|
|
||||||
try {
|
|
||||||
// Create repository savepoint here so we can rollback to it after testing transactions
|
|
||||||
repository.setSavepoint();
|
|
||||||
|
|
||||||
for (Transaction transaction : this.getTransactions()) {
|
|
||||||
TransactionData transactionData = transaction.getTransactionData();
|
|
||||||
|
|
||||||
// GenesisTransactions are not allowed (GenesisBlock overrides isValid() to allow them)
|
|
||||||
if (transactionData.getType() == TransactionType.GENESIS || transactionData.getType() == TransactionType.ACCOUNT_FLAGS)
|
|
||||||
return ValidationResult.GENESIS_TRANSACTIONS_INVALID;
|
|
||||||
|
|
||||||
// Check timestamp and deadline
|
|
||||||
if (transactionData.getTimestamp() > this.blockData.getTimestamp()
|
|
||||||
|| transaction.getDeadline() <= this.blockData.getTimestamp())
|
|
||||||
return ValidationResult.TRANSACTION_TIMESTAMP_INVALID;
|
|
||||||
|
|
||||||
// Check transaction isn't already included in a block
|
|
||||||
if (this.repository.getTransactionRepository().isConfirmed(transactionData.getSignature()))
|
|
||||||
return ValidationResult.TRANSACTION_ALREADY_PROCESSED;
|
|
||||||
|
|
||||||
// Check transaction has correct reference, etc.
|
|
||||||
if (!transaction.hasValidReference()) {
|
|
||||||
LOGGER.debug("Error during transaction validation, tx " + Base58.encode(transactionData.getSignature()) + ": INVALID_REFERENCE");
|
|
||||||
return ValidationResult.TRANSACTION_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check transaction is even valid
|
|
||||||
// NOTE: in Gen1 there was an extra block height passed to DeployATTransaction.isValid
|
|
||||||
Transaction.ValidationResult validationResult = transaction.isValid();
|
|
||||||
if (validationResult != Transaction.ValidationResult.OK) {
|
|
||||||
LOGGER.debug("Error during transaction validation, tx " + Base58.encode(transactionData.getSignature()) + ": "
|
|
||||||
+ validationResult.name());
|
|
||||||
return ValidationResult.TRANSACTION_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check transaction can even be processed
|
|
||||||
validationResult = transaction.isProcessable();
|
|
||||||
if (validationResult != Transaction.ValidationResult.OK) {
|
|
||||||
LOGGER.debug("Error during transaction validation, tx " + Base58.encode(transactionData.getSignature()) + ": "
|
|
||||||
+ validationResult.name());
|
|
||||||
return ValidationResult.TRANSACTION_INVALID;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process transaction to make sure other transactions validate properly
|
|
||||||
try {
|
|
||||||
// Only process transactions that don't require group-approval.
|
|
||||||
// Group-approval transactions are dealt with later.
|
|
||||||
if (transactionData.getApprovalStatus() == ApprovalStatus.NOT_REQUIRED)
|
|
||||||
transaction.process();
|
|
||||||
|
|
||||||
// Regardless of group-approval, update relevant info for creator (e.g. lastReference)
|
|
||||||
transaction.processReferencesAndFees();
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOGGER.error("Exception during transaction validation, tx " + Base58.encode(transactionData.getSignature()), e);
|
|
||||||
e.printStackTrace();
|
|
||||||
return ValidationResult.TRANSACTION_PROCESSING_FAILED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (DataException e) {
|
|
||||||
return ValidationResult.TRANSACTION_INVALID;
|
|
||||||
} finally {
|
|
||||||
// Rollback repository changes made by test-processing transactions above
|
|
||||||
try {
|
|
||||||
this.repository.rollbackToSavepoint();
|
|
||||||
} catch (DataException e) {
|
|
||||||
/*
|
|
||||||
* Rollback failure most likely due to prior DataException, so discard this DataException. Prior DataException propagates to caller.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Block is valid
|
|
||||||
return ValidationResult.OK;
|
return ValidationResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1091,9 +1114,9 @@ public class Block {
|
|||||||
throw new IllegalStateException("Attempted to execute ATs when block's local AT state data already exists");
|
throw new IllegalStateException("Attempted to execute ATs when block's local AT state data already exists");
|
||||||
|
|
||||||
// AT-Transactions generated by running ATs, to be prepended to block's transactions
|
// AT-Transactions generated by running ATs, to be prepended to block's transactions
|
||||||
List<AtTransaction> allATTransactions = new ArrayList<AtTransaction>();
|
List<AtTransaction> allATTransactions = new ArrayList<>();
|
||||||
|
|
||||||
this.ourAtStates = new ArrayList<ATStateData>();
|
this.ourAtStates = new ArrayList<>();
|
||||||
this.ourAtFees = BigDecimal.ZERO.setScale(8);
|
this.ourAtFees = BigDecimal.ZERO.setScale(8);
|
||||||
|
|
||||||
// Find all executable ATs, ordered by earliest creation date first
|
// Find all executable ATs, ordered by earliest creation date first
|
||||||
@ -1323,7 +1346,7 @@ public class Block {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// APPROVED, in which case do transaction.process();
|
// APPROVED, process transaction
|
||||||
transactionData.setApprovalStatus(ApprovalStatus.APPROVED);
|
transactionData.setApprovalStatus(ApprovalStatus.APPROVED);
|
||||||
transactionRepository.save(transactionData);
|
transactionRepository.save(transactionData);
|
||||||
|
|
||||||
@ -1376,7 +1399,7 @@ public class Block {
|
|||||||
transactionRepository.confirmTransaction(transactionData.getSignature());
|
transactionRepository.confirmTransaction(transactionData.getSignature());
|
||||||
|
|
||||||
List<Account> participants = transaction.getInvolvedAccounts();
|
List<Account> participants = transaction.getInvolvedAccounts();
|
||||||
List<String> participantAddresses = participants.stream().map(account -> account.getAddress()).collect(Collectors.toList());
|
List<String> participantAddresses = participants.stream().map(Account::getAddress).collect(Collectors.toList());
|
||||||
transactionRepository.saveParticipants(transactionData, participantAddresses);
|
transactionRepository.saveParticipants(transactionData, participantAddresses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +178,7 @@ public class BlockChain {
|
|||||||
StreamSource jsonSource;
|
StreamSource jsonSource;
|
||||||
|
|
||||||
if (filename != null) {
|
if (filename != null) {
|
||||||
LOGGER.info("Using blockchain config file: " + path + filename);
|
LOGGER.info(String.format("Using blockchain config file: %s%s", path, filename));
|
||||||
|
|
||||||
File jsonFile = new File(path + filename);
|
File jsonFile = new File(path + filename);
|
||||||
|
|
||||||
@ -221,8 +221,8 @@ public class BlockChain {
|
|||||||
blockchain.validateConfig();
|
blockchain.validateConfig();
|
||||||
|
|
||||||
// Minor fix-up
|
// Minor fix-up
|
||||||
blockchain.maxBytesPerUnitFee.setScale(8);
|
blockchain.maxBytesPerUnitFee = blockchain.maxBytesPerUnitFee.setScale(8);
|
||||||
blockchain.unitFee.setScale(8);
|
blockchain.unitFee = blockchain.unitFee.setScale(8);
|
||||||
blockchain.minFeePerByte = blockchain.unitFee.divide(blockchain.maxBytesPerUnitFee, MathContext.DECIMAL32);
|
blockchain.minFeePerByte = blockchain.unitFee.divide(blockchain.maxBytesPerUnitFee, MathContext.DECIMAL32);
|
||||||
|
|
||||||
// Successfully read config now in effect
|
// Successfully read config now in effect
|
||||||
@ -509,8 +509,7 @@ public class BlockChain {
|
|||||||
|
|
||||||
repository.saveChanges();
|
repository.saveChanges();
|
||||||
} catch (DataException e) {
|
} catch (DataException e) {
|
||||||
LOGGER.warn("Repository issue trying to trim old online accounts signatures: " + e.getMessage());
|
LOGGER.warn(String.format("Repository issue trying to trim old online accounts signatures: %s", e.getMessage()));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user