diff --git a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java index 9a11a820..ca5ce517 100644 --- a/src/main/java/org/qortal/transaction/ArbitraryTransaction.java +++ b/src/main/java/org/qortal/transaction/ArbitraryTransaction.java @@ -20,6 +20,7 @@ import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.arbitrary.ArbitraryDataFile; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.ArbitraryTransactionTransformer; import org.qortal.transform.transaction.TransactionTransformer; import org.qortal.utils.ArbitraryTransactionUtils; @@ -90,8 +91,9 @@ public class ArbitraryTransaction extends Transaction { // Disable reference checking after feature trigger timestamp if (this.arbitraryTransactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { - // Allow any non-null value - return this.arbitraryTransactionData.getReference() != null; + // Allow any value as long as it is the correct length + return this.arbitraryTransactionData.getReference() != null && + this.arbitraryTransactionData.getReference().length == Transformer.SIGNATURE_LENGTH; } if (this.arbitraryTransactionData.getReference() == null) { diff --git a/src/main/java/org/qortal/transaction/AtTransaction.java b/src/main/java/org/qortal/transaction/AtTransaction.java index be0388a1..b07f006b 100644 --- a/src/main/java/org/qortal/transaction/AtTransaction.java +++ b/src/main/java/org/qortal/transaction/AtTransaction.java @@ -13,6 +13,7 @@ import org.qortal.data.transaction.TransactionData; import org.qortal.repository.DataException; import org.qortal.repository.Repository; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.AtTransactionTransformer; import org.qortal.utils.Amounts; @@ -78,8 +79,9 @@ public class AtTransaction extends Transaction { public boolean hasValidReference() throws DataException { // Disable reference checking after feature trigger timestamp if (this.atTransactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { - // Allow any non-null value - return this.atTransactionData.getReference() != null; + // Allow any value as long as it is the correct length + return this.atTransactionData.getReference() != null && + this.atTransactionData.getReference().length == Transformer.SIGNATURE_LENGTH; } // Check reference is correct, using AT account, not transaction creator which is null account diff --git a/src/main/java/org/qortal/transaction/MessageTransaction.java b/src/main/java/org/qortal/transaction/MessageTransaction.java index 4540bea6..a9d3a01c 100644 --- a/src/main/java/org/qortal/transaction/MessageTransaction.java +++ b/src/main/java/org/qortal/transaction/MessageTransaction.java @@ -21,6 +21,7 @@ import org.qortal.repository.DataException; import org.qortal.repository.GroupRepository; import org.qortal.repository.Repository; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.ChatTransactionTransformer; import org.qortal.transform.transaction.MessageTransactionTransformer; import org.qortal.transform.transaction.TransactionTransformer; @@ -167,8 +168,9 @@ public class MessageTransaction extends Transaction { // Disable reference checking after feature trigger timestamp if (this.messageTransactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { - // Allow any non-null value - return this.messageTransactionData.getReference() != null; + // Allow any value as long as it is the correct length + return this.messageTransactionData.getReference() != null && + this.messageTransactionData.getReference().length == Transformer.SIGNATURE_LENGTH; } if (this.messageTransactionData.getReference() == null) diff --git a/src/main/java/org/qortal/transaction/Transaction.java b/src/main/java/org/qortal/transaction/Transaction.java index 9f56af6b..b56d48cf 100644 --- a/src/main/java/org/qortal/transaction/Transaction.java +++ b/src/main/java/org/qortal/transaction/Transaction.java @@ -31,6 +31,7 @@ import org.qortal.repository.GroupRepository; import org.qortal.repository.Repository; import org.qortal.settings.Settings; import org.qortal.transform.TransformationException; +import org.qortal.transform.Transformer; import org.qortal.transform.transaction.TransactionTransformer; import org.qortal.utils.NTP; @@ -907,8 +908,9 @@ public abstract class Transaction { public boolean hasValidReference() throws DataException { // Disable reference checking after feature trigger timestamp if (this.transactionData.getTimestamp() >= BlockChain.getInstance().getDisableReferenceTimestamp()) { - // Allow any non-null value - return this.transactionData.getReference() != null; + // Allow any value as long as it is the correct length + return this.transactionData.getReference() != null && + this.transactionData.getReference().length == Transformer.SIGNATURE_LENGTH; } Account creator = getCreator(); diff --git a/src/test/java/org/qortal/test/TransactionReferenceTests.java b/src/test/java/org/qortal/test/TransactionReferenceTests.java index 32a8da82..fdff8b59 100644 --- a/src/test/java/org/qortal/test/TransactionReferenceTests.java +++ b/src/test/java/org/qortal/test/TransactionReferenceTests.java @@ -122,16 +122,43 @@ public class TransactionReferenceTests extends Common { TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); // Set a 1-byte reference - byte[] randomByte = new byte[1]; + byte[] randomByte = new byte[63]; random.nextBytes(randomByte); paymentTransactionData.setReference(randomByte); Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); - // Transaction should be valid, as any non-null value is allowed + // Transaction should be invalid, as reference isn't long enough Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); - assertEquals(Transaction.ValidationResult.OK, validationResult); - TransactionUtils.signAndImportValid(repository, paymentTransactionData, alice); + assertEquals(Transaction.ValidationResult.INVALID_REFERENCE, validationResult); + } + } + + @Test + public void testLongReferenceAfterFeatureTrigger() throws DataException { + Common.useSettings("test-settings-v2-disable-reference.json"); + Random random = new Random(); + + try (final Repository repository = RepositoryManager.getRepository()) { + PrivateKeyAccount alice = Common.getTestAccount(repository, "alice"); + + byte[] randomPrivateKey = new byte[32]; + random.nextBytes(randomPrivateKey); + PrivateKeyAccount recipient = new PrivateKeyAccount(repository, randomPrivateKey); + + // Create payment transaction data + TransactionData paymentTransactionData = new PaymentTransactionData(TestTransaction.generateBase(alice), recipient.getAddress(), 100000L); + + // Set a 1-byte reference + byte[] randomByte = new byte[65]; + random.nextBytes(randomByte); + paymentTransactionData.setReference(randomByte); + + Transaction paymentTransaction = Transaction.fromData(repository, paymentTransactionData); + + // Transaction should be invalid, as reference is too long + Transaction.ValidationResult validationResult = paymentTransaction.isValidUnconfirmed(); + assertEquals(Transaction.ValidationResult.INVALID_REFERENCE, validationResult); } }