forked from Qortal/qortal
Merge branch 'master' into block-sequence
This commit is contained in:
commit
9566bda279
2
pom.xml
2
pom.xml
@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.qortal</groupId>
|
||||
<artifactId>qortal</artifactId>
|
||||
<version>3.8.5</version>
|
||||
<version>3.8.9</version>
|
||||
<packaging>jar</packaging>
|
||||
<properties>
|
||||
<skipTests>true</skipTests>
|
||||
|
@ -60,7 +60,7 @@ public class BootstrapResource {
|
||||
bootstrap.validateBlockchain();
|
||||
return bootstrap.create();
|
||||
|
||||
} catch (DataException | InterruptedException | IOException e) {
|
||||
} catch (Exception e) {
|
||||
LOGGER.info("Unable to create bootstrap", e);
|
||||
throw ApiExceptionFactory.INSTANCE.createCustomException(request, ApiError.REPOSITORY_ISSUE, e.getMessage());
|
||||
}
|
||||
|
@ -84,6 +84,8 @@ public enum Service {
|
||||
QCHAT_IMAGE(420, true, 500*1024L, null),
|
||||
VIDEO(500, false, null, null),
|
||||
AUDIO(600, false, null, null),
|
||||
QCHAT_AUDIO(610, true, 10*1024*1024L, null),
|
||||
QCHAT_VOICE(620, true, 10*1024*1024L, null),
|
||||
BLOG(700, false, null, null),
|
||||
BLOG_POST(777, false, null, null),
|
||||
BLOG_COMMENT(778, false, null, null),
|
||||
|
@ -204,7 +204,7 @@ public class ArbitraryDataCleanupManager extends Thread {
|
||||
|
||||
if (completeFileExists && !allChunksExist) {
|
||||
// We have the complete file but not the chunks, so let's convert it
|
||||
LOGGER.info(String.format("Transaction %s has complete file but no chunks",
|
||||
LOGGER.debug(String.format("Transaction %s has complete file but no chunks",
|
||||
Base58.encode(arbitraryTransactionData.getSignature())));
|
||||
|
||||
ArbitraryTransactionUtils.convertFileToChunks(arbitraryTransactionData, now, STALE_FILE_TIMEOUT);
|
||||
|
@ -16,6 +16,8 @@ import org.qortal.repository.Repository;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
import org.qortal.utils.Unicode;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class Name {
|
||||
|
||||
// Properties
|
||||
@ -116,7 +118,7 @@ public class Name {
|
||||
|
||||
this.repository.getNameRepository().save(this.nameData);
|
||||
|
||||
if (!updateNameTransactionData.getNewName().isEmpty())
|
||||
if (!updateNameTransactionData.getNewName().isEmpty() && !Objects.equals(updateNameTransactionData.getName(), updateNameTransactionData.getNewName()))
|
||||
// Name has changed, delete old entry
|
||||
this.repository.getNameRepository().delete(updateNameTransactionData.getNewName());
|
||||
|
||||
|
@ -279,7 +279,9 @@ public class Bootstrap {
|
||||
|
||||
LOGGER.info("Generating checksum file...");
|
||||
String checksum = Crypto.digestHexString(compressedOutputPath.toFile(), 1024*1024);
|
||||
LOGGER.info("checksum: {}", checksum);
|
||||
Path checksumPath = Paths.get(String.format("%s.sha256", compressedOutputPath.toString()));
|
||||
LOGGER.info("Writing checksum to path: {}", checksumPath);
|
||||
Files.writeString(checksumPath, checksum, StandardOpenOption.CREATE);
|
||||
|
||||
// Return the path to the compressed bootstrap file
|
||||
|
@ -215,7 +215,7 @@ public class Settings {
|
||||
public long recoveryModeTimeout = 10 * 60 * 1000L;
|
||||
|
||||
/** Minimum peer version number required in order to sync with them */
|
||||
private String minPeerVersion = "3.8.2";
|
||||
private String minPeerVersion = "3.8.7";
|
||||
/** Whether to allow connections with peers below minPeerVersion
|
||||
* If true, we won't sync with them but they can still sync with us, and will show in the peers list
|
||||
* If false, sync will be blocked both ways, and they will not appear in the peers list */
|
||||
|
@ -5,6 +5,7 @@ import java.util.List;
|
||||
|
||||
import org.qortal.account.Account;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.controller.repository.NamesDatabaseIntegrityCheck;
|
||||
import org.qortal.data.naming.NameData;
|
||||
import org.qortal.data.transaction.CancelSellNameTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
@ -81,7 +82,13 @@ public class CancelSellNameTransaction extends Transaction {
|
||||
|
||||
@Override
|
||||
public void preProcess() throws DataException {
|
||||
// Nothing to do
|
||||
CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
|
||||
|
||||
// Rebuild this name in the Names table from the transaction history
|
||||
// This is necessary because in some rare cases names can be missing from the Names table after registration
|
||||
// but we have been unable to reproduce the issue and track down the root cause
|
||||
NamesDatabaseIntegrityCheck namesDatabaseIntegrityCheck = new NamesDatabaseIntegrityCheck();
|
||||
namesDatabaseIntegrityCheck.rebuildName(cancelSellNameTransactionData.getName(), this.repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -219,6 +219,65 @@ public class UpdateTests extends Common {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that multiple UPDATE_NAME transactions work as expected, when using a matching name and newName string
|
||||
@Test
|
||||
public void testDoubleUpdateNameWithMatchingNewName() throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
// Register-name
|
||||
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
|
||||
String name = "name";
|
||||
String reducedName = "name";
|
||||
String data = "{\"age\":30}";
|
||||
|
||||
TransactionData initialTransactionData = new RegisterNameTransactionData(TestTransaction.generateBase(alice), name, data);
|
||||
initialTransactionData.setFee(new RegisterNameTransaction(null, null).getUnitFee(initialTransactionData.getTimestamp()));
|
||||
TransactionUtils.signAndMint(repository, initialTransactionData, alice);
|
||||
|
||||
// Check name exists
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
assertNotNull(repository.getNameRepository().fromReducedName(reducedName));
|
||||
|
||||
// Update name
|
||||
TransactionData middleTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), name, name, data);
|
||||
TransactionUtils.signAndMint(repository, middleTransactionData, alice);
|
||||
|
||||
// Check name still exists
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
assertNotNull(repository.getNameRepository().fromReducedName(reducedName));
|
||||
|
||||
// Update name again
|
||||
TransactionData newestTransactionData = new UpdateNameTransactionData(TestTransaction.generateBase(alice), name, name, data);
|
||||
TransactionUtils.signAndMint(repository, newestTransactionData, alice);
|
||||
|
||||
// Check name still exists
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
assertNotNull(repository.getNameRepository().fromReducedName(reducedName));
|
||||
|
||||
// Check updated timestamp is correct
|
||||
assertEquals((Long) newestTransactionData.getTimestamp(), repository.getNameRepository().fromName(name).getUpdated());
|
||||
|
||||
// orphan and recheck
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Check name still exists
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
assertNotNull(repository.getNameRepository().fromReducedName(reducedName));
|
||||
|
||||
// Check updated timestamp is correct
|
||||
assertEquals((Long) middleTransactionData.getTimestamp(), repository.getNameRepository().fromName(name).getUpdated());
|
||||
|
||||
// orphan and recheck
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
|
||||
// Check name still exists
|
||||
assertTrue(repository.getNameRepository().nameExists(name));
|
||||
assertNotNull(repository.getNameRepository().fromReducedName(reducedName));
|
||||
|
||||
// Check updated timestamp is empty
|
||||
assertNull(repository.getNameRepository().fromName(name).getUpdated());
|
||||
}
|
||||
}
|
||||
|
||||
// Test that reverting using previous UPDATE_NAME works as expected
|
||||
@Test
|
||||
public void testIntermediateUpdateName() throws DataException {
|
||||
|
Loading…
Reference in New Issue
Block a user