Browse Source

Change auto-update to required approved tx created by non-admin.

Previously it was possible broadcast an auto-update tx that was
created by a 'dev' group admin.

Now the auto-update tx must be created by a 'dev' group non-admin/owner
and hence require group approval before it takes effect.

To this end, a new TransactionRepository.getLatestAutoUpdateTransaction()
method has been added to simplify finding the latest matching, approved
auto-update transaction.

Corresponding changes also made to AutoUpdate.run()
split-DB
catbref 5 years ago
parent
commit
3e3c0affb0
  1. 10
      src/main/java/org/qora/controller/AutoUpdate.java
  2. 38
      src/main/java/org/qora/repository/TransactionRepository.java
  3. 45
      src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java

10
src/main/java/org/qora/controller/AutoUpdate.java

@ -19,7 +19,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qora.ApplyUpdate;
import org.qora.api.ApiRequest;
import org.qora.api.resource.TransactionsResource.ConfirmationStatus;
import org.qora.data.transaction.ArbitraryTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.gui.SysTray;
@ -45,7 +44,6 @@ public class AutoUpdate extends Thread {
private static final int DEV_GROUP_ID = 1;
private static final int UPDATE_SERVICE = 1;
private static final List<TransactionType> ARBITRARY_TX_TYPE = Arrays.asList(TransactionType.ARBITRARY);
private static final int GIT_COMMIT_HASH_LENGTH = 20; // SHA-1
private static final int EXPECTED_DATA_LENGTH = Transformer.TIMESTAMP_LENGTH + GIT_COMMIT_HASH_LENGTH + Transformer.SHA256_LENGTH;
@ -81,7 +79,7 @@ public class AutoUpdate extends Thread {
return;
}
// Try to clean up any leftover downloads (but if we are/have attempted update then don't delete new JAR)
// Try to clean up any leftover downloads (but if have attempted update then don't delete new JAR)
if (!attemptedUpdate)
try {
Path newJar = Paths.get(NEW_JAR_FILENAME);
@ -92,11 +90,11 @@ public class AutoUpdate extends Thread {
// Look for "update" tx which is arbitrary tx in dev-group with service 1 and timestamp later than buildTimestamp
try (final Repository repository = RepositoryManager.getRepository()) {
List<byte[]> signatures = repository.getTransactionRepository().getSignaturesMatchingCriteria(null, null, DEV_GROUP_ID, ARBITRARY_TX_TYPE, UPDATE_SERVICE, null, ConfirmationStatus.CONFIRMED, 1, null, true);
if (signatures == null || signatures.isEmpty())
byte[] signature = repository.getTransactionRepository().getLatestAutoUpdateTransaction(TransactionType.ARBITRARY, DEV_GROUP_ID, UPDATE_SERVICE);
if (signature == null)
continue;
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signatures.get(0));
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
if (!(transactionData instanceof ArbitraryTransactionData))
continue;

38
src/main/java/org/qora/repository/TransactionRepository.java

@ -47,10 +47,48 @@ public interface TransactionRepository {
*/
public Map<TransactionType, Integer> getTransactionSummary(int startHeight, int endHeight) throws DataException;
/**
* Returns signatures for transactions that match search criteria.
* <p>
* If <tt>blockLimit</tt> is specified, and <tt>startBlock</tt> is <tt>null</tt>,
* then <tt>startBlock</tt> is assumed to be 1 or max-block-height,
* depending on <tt>reverse</tt> being <tt>false</tt> or <tt>true</tt>
* respectively.
*
* @param startBlock height of first block to check
* @param blockLimit number of blocks (from <tt>startBlock</tt>) to check
* @param txGroupId
* @param txTypes
* @param service arbitrary transaction service ID
* @param address
* @param confirmationStatus
* @param limit
* @param offset
* @param reverse
* @return
* @throws DataException
*/
public List<byte[]> getSignaturesMatchingCriteria(Integer startBlock, Integer blockLimit, Integer txGroupId,
List<TransactionType> txTypes, Integer service, String address,
ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse) throws DataException;
/**
* Returns signature for latest auto-update transaction.
* <p>
* Transaction must be <tt>CONFIRMED</tt> and <tt>APPROVED</tt>
* and also <b>not</b> created by group admin/owner.
* <p>
* We can check the latter by testing for transaction's <tt>approvalHeight</tt>
* being greater than <tt>blockHeight</tt>.
*
* @param txType
* @param txGroupId
* @param service
* @return
* @throws DataException
*/
public byte[] getLatestAutoUpdateTransaction(TransactionType txType, int txGroupId, Integer service) throws DataException;
/**
* Returns list of transactions relating to specific asset ID.
*

45
src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java

@ -512,6 +512,51 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
}
}
@Override
public byte[] getLatestAutoUpdateTransaction(TransactionType txType, int txGroupId, Integer service) throws DataException {
StringBuilder sql = new StringBuilder(1024);
sql.append("SELECT Transactions.signature FROM Transactions");
if (service != null) {
// This is for ARBITRARY transactions
sql.append(" LEFT OUTER JOIN ArbitraryTransactions ON ArbitraryTransactions.signature = Transactions.signature");
}
sql.append(" WHERE type = ");
// Enum int value safe to use literally
sql.append(txType.value);
sql.append(" AND tx_group_id = ");
// int value safe to use literally
sql.append(txGroupId);
if (service != null) {
// This is for ARBITRARY transactions
sql.append(" AND service = ");
// int value safe to use literally
sql.append(service);
}
// "approvalHeight > blockHeight" filters out 'auto-approved' transactions, i.e. those by group admins/owner
sql.append(" AND block_height IS NOT NULL AND approval_height IS NOT NULL AND approval_height > block_height");
// we want approved, not rejected!
sql.append(" AND approval_status = ");
// Enum int value safe to use literally
sql.append(ApprovalStatus.APPROVED.value);
sql.append(" ORDER BY creation DESC LIMIT 1");
try (ResultSet resultSet = this.repository.checkedExecute(sql.toString())) {
if (resultSet == null)
return null;
return resultSet.getBytes(1);
} catch (SQLException e) {
throw new DataException("Unable to fetch latest auto-update transaction signature from repository", e);
}
}
@Override
public List<TransactionData> getAssetTransactions(long assetId, ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse)
throws DataException {

Loading…
Cancel
Save