Unify setting Transaction's initial group-approval status.

Refactored duplicate code into Transaction.setInitialApprovalStatus().

This is make sure transactions HAVE a group-approval status
in Synchronizer before Block.isValid is called.

This wasn't a problem for new, unconfirmed, individual transactions
arriving over the wire due to Transaction.importAsUnconfirmed()
doing the right thing.

Also added a groupApprovalTimestamp to BlockChain feature-triggers
to support legacy chains.

Tested by syncing mainnet from scratch.
This commit is contained in:
catbref 2019-07-02 11:37:03 +01:00
parent ad827ae01d
commit 192a072796
4 changed files with 27 additions and 18 deletions

View File

@ -78,7 +78,8 @@ public class BlockChain {
arbitraryTimestamp, arbitraryTimestamp,
powfixTimestamp, powfixTimestamp,
v2Timestamp, v2Timestamp,
newAssetPricingTimestamp; newAssetPricingTimestamp,
groupApprovalTimestamp;
} }
/** Map of which blockchain features are enabled when (height/timestamp) */ /** Map of which blockchain features are enabled when (height/timestamp) */
@ -299,6 +300,10 @@ public class BlockChain {
return featureTriggers.get("newAssetPricingTimestamp"); return featureTriggers.get("newAssetPricingTimestamp");
} }
public long getGroupApprovalTimestamp() {
return featureTriggers.get("groupApprovalTimestamp");
}
// More complex getters for aspects that change by height or timestamp // More complex getters for aspects that change by height or timestamp
public BigDecimal getRewardAtHeight(int ourHeight) { public BigDecimal getRewardAtHeight(int ourHeight) {

View File

@ -26,7 +26,6 @@ import org.qora.repository.DataException;
import org.qora.repository.Repository; import org.qora.repository.Repository;
import org.qora.repository.RepositoryManager; import org.qora.repository.RepositoryManager;
import org.qora.transaction.Transaction; import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.ApprovalStatus;
public class Synchronizer { public class Synchronizer {
@ -252,6 +251,10 @@ public class Synchronizer {
return SynchronizationResult.INVALID_DATA; return SynchronizationResult.INVALID_DATA;
} }
// Transactions are transmitted without approval status so determine that now
for (Transaction transaction : newBlock.getTransactions())
transaction.setInitialApprovalStatus();
ValidationResult blockResult = newBlock.isValid(); ValidationResult blockResult = newBlock.isValid();
if (blockResult != ValidationResult.OK) { if (blockResult != ValidationResult.OK) {
LOGGER.info(String.format("Peer %s sent invalid block for height %d: %s", peer, ourHeight, blockResult.name())); LOGGER.info(String.format("Peer %s sent invalid block for height %d: %s", peer, ourHeight, blockResult.name()));
@ -261,14 +264,6 @@ public class Synchronizer {
// Save transactions attached to this block // Save transactions attached to this block
for (Transaction transaction : newBlock.getTransactions()) { for (Transaction transaction : newBlock.getTransactions()) {
TransactionData transactionData = transaction.getTransactionData(); TransactionData transactionData = transaction.getTransactionData();
// Fix up approval status
if (transaction.needsGroupApproval()) {
transactionData.setApprovalStatus(ApprovalStatus.PENDING);
} else {
transactionData.setApprovalStatus(ApprovalStatus.NOT_REQUIRED);
}
repository.getTransactionRepository().save(transactionData); repository.getTransactionRepository().save(transactionData);
} }

View File

@ -778,6 +778,10 @@ public abstract class Transaction {
if (!this.transactionData.getType().needsApproval) if (!this.transactionData.getType().needsApproval)
return false; return false;
// Is group-approval even in effect yet?
if (this.transactionData.getTimestamp() < BlockChain.getInstance().getGroupApprovalTimestamp())
return false;
int txGroupId = this.transactionData.getTxGroupId(); int txGroupId = this.transactionData.getTxGroupId();
if (txGroupId == Group.NO_GROUP) if (txGroupId == Group.NO_GROUP)
@ -797,6 +801,14 @@ public abstract class Transaction {
return true; return true;
} }
public void setInitialApprovalStatus() throws DataException {
if (this.needsGroupApproval()) {
transactionData.setApprovalStatus(ApprovalStatus.PENDING);
} else {
transactionData.setApprovalStatus(ApprovalStatus.NOT_REQUIRED);
}
}
public Boolean getApprovalDecision() throws DataException { public Boolean getApprovalDecision() throws DataException {
// Grab latest decisions from repository // Grab latest decisions from repository
GroupApprovalData groupApprovalData = this.repository.getTransactionRepository().getApprovalData(this.transactionData.getSignature()); GroupApprovalData groupApprovalData = this.repository.getTransactionRepository().getApprovalData(this.transactionData.getSignature());
@ -841,17 +853,13 @@ public abstract class Transaction {
if (repository.getTransactionRepository().exists(transactionData.getSignature())) if (repository.getTransactionRepository().exists(transactionData.getSignature()))
return ValidationResult.TRANSACTION_ALREADY_EXISTS; return ValidationResult.TRANSACTION_ALREADY_EXISTS;
// Fix up approval status
this.setInitialApprovalStatus();
ValidationResult validationResult = this.isValidUnconfirmed(); ValidationResult validationResult = this.isValidUnconfirmed();
if (validationResult != ValidationResult.OK) if (validationResult != ValidationResult.OK)
return validationResult; return validationResult;
// Fix up approval status
if (this.needsGroupApproval()) {
transactionData.setApprovalStatus(ApprovalStatus.PENDING);
} else {
transactionData.setApprovalStatus(ApprovalStatus.NOT_REQUIRED);
}
repository.getTransactionRepository().save(transactionData); repository.getTransactionRepository().save(transactionData);
repository.getTransactionRepository().unconfirmTransaction(transactionData); repository.getTransactionRepository().unconfirmTransaction(transactionData);
repository.saveChanges(); repository.saveChanges();

View File

@ -167,6 +167,7 @@
"arbitraryTimestamp": "1405702800000", "arbitraryTimestamp": "1405702800000",
"powfixTimestamp": "1456426800000", "powfixTimestamp": "1456426800000",
"v2Timestamp": "1559347200000", "v2Timestamp": "1559347200000",
"newAssetPricingTimestamp": "2000000000000" "newAssetPricingTimestamp": "2000000000000",
"groupApprovalTimestamp": "2000000000000"
} }
} }