Browse Source

Reference fixes for MESSAGE transactions & tests to cover

split-DB
catbref 4 years ago
parent
commit
faa6405d5f
  1. 33
      src/main/java/org/qortal/transaction/MessageTransaction.java
  2. 56
      src/test/java/org/qortal/test/MessageTests.java

33
src/main/java/org/qortal/transaction/MessageTransaction.java

@ -2,13 +2,16 @@ package org.qortal.transaction;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.qortal.account.Account;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.account.PublicKeyAccount;
import org.qortal.asset.Asset;
import org.qortal.crypto.Crypto;
import org.qortal.crypto.MemoryPoW;
import org.qortal.data.PaymentData;
import org.qortal.data.transaction.BaseTransactionData;
import org.qortal.data.transaction.MessageTransactionData;
import org.qortal.data.transaction.TransactionData;
import org.qortal.group.Group;
@ -20,6 +23,7 @@ import org.qortal.transform.TransformationException;
import org.qortal.transform.transaction.ChatTransactionTransformer;
import org.qortal.transform.transaction.MessageTransactionTransformer;
import org.qortal.transform.transaction.TransactionTransformer;
import org.qortal.utils.NTP;
public class MessageTransaction extends Transaction {
@ -45,6 +49,22 @@ public class MessageTransaction extends Transaction {
this.messageTransactionData = (MessageTransactionData) this.transactionData;
}
/** Constructs non-payment MessageTransaction. Caller will need to compute nonce/set fee and then sign. */
public static MessageTransaction build(Repository repository, PrivateKeyAccount sender, int txGroupId, String recipient, byte[] data, boolean isText, boolean isEncrypted) throws DataException {
long timestamp = NTP.getTime();
byte[] reference = sender.getLastReference();
if (reference == null) {
reference = new byte[64];
new Random().nextBytes(reference);
}
long fee = 0L;
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, txGroupId, reference, sender.getPublicKey(), fee, null);
int version = 4;
MessageTransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, version, 0, recipient, 0, null, data, isText, isEncrypted);
return new MessageTransaction(repository, messageTransactionData);
}
// More information
@Override
@ -140,6 +160,19 @@ public class MessageTransaction extends Transaction {
return ValidationResult.OK;
}
@Override
public boolean hasValidReference() throws DataException {
// We shouldn't really get this far, but just in case:
if (this.messageTransactionData.getReference() == null)
return false;
// If zero fee, then we rely on nonce and reference isn't important
if (this.messageTransactionData.getFee() == 0)
return true;
return super.hasValidReference();
}
@Override
public ValidationResult isValid() throws DataException {
// Nonce checking is done via isSignatureValid() as that method is only called once per import

56
src/test/java/org/qortal/test/MessageTests.java

@ -3,7 +3,10 @@ package org.qortal.test;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.qortal.account.PrivateKeyAccount;
import org.qortal.asset.Asset;
import org.qortal.block.BlockChain;
import org.qortal.data.transaction.BaseTransactionData;
import org.qortal.data.transaction.MessageTransactionData;
import org.qortal.data.transaction.TransactionData;
import org.qortal.group.Group;
@ -24,9 +27,12 @@ import org.qortal.transaction.Transaction.ValidationResult;
import org.qortal.transform.TransformationException;
import org.qortal.transform.transaction.MessageTransactionTransformer;
import org.qortal.transform.transaction.TransactionTransformer;
import org.qortal.utils.NTP;
import static org.junit.Assert.*;
import java.util.Random;
public class MessageTests extends Common {
private static final int version = 4;
@ -69,6 +75,44 @@ public class MessageTests extends Common {
assertFalse(isValid(newGroupId, null, 0L, null));
}
@Test
public void referenceTests() throws DataException {
Random random = new Random();
byte[] randomPrivateKey = new byte[32];
random.nextBytes(randomPrivateKey);
byte[] randomReference = new byte[64];
random.nextBytes(randomReference);
long minimumFee = BlockChain.getInstance().getUnitFee();
try (final Repository repository = RepositoryManager.getRepository()) {
PrivateKeyAccount alice = Common.getTestAccount(repository, "alice");
PrivateKeyAccount newbie = new PrivateKeyAccount(repository, randomPrivateKey);
byte[] aliceReference = alice.getLastReference();
// real account, correct reference, real fee: OK
assertTrue(hasValidReference(repository, alice, aliceReference, minimumFee));
// real account, random reference, real fee: INVALID
assertFalse(hasValidReference(repository, alice, randomReference, minimumFee));
// real account, correct reference, zero fee: OK
assertTrue(hasValidReference(repository, alice, aliceReference, 0));
// real account, random reference, zero fee: OK
assertTrue(hasValidReference(repository, alice, randomReference, 0));
// new account, null reference, real fee: INVALID: new accounts don't have a reference!
assertFalse(hasValidReference(repository, newbie, null, minimumFee));
// new account, wrong reference, real fee: INVALID: new accounts don't have a reference!
assertFalse(hasValidReference(repository, newbie, randomReference, minimumFee));
// new account, null reference, zero fee: INVALID
assertFalse(hasValidReference(repository, newbie, null, 0));
// new account, random reference, zero fee: OK
assertTrue(hasValidReference(repository, newbie, randomReference, 0));
}
}
@Test
public void noFeeNoNonce() throws DataException {
testFeeNonce(false, false, false);
@ -139,6 +183,18 @@ public class MessageTests extends Common {
}
}
private boolean hasValidReference(Repository repository, PrivateKeyAccount sender, byte[] reference, long fee) throws DataException {
long timestamp = NTP.getTime();
BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, sender.getPublicKey(), fee, null);
int version = 4;
byte[] data = "test".getBytes();
boolean isText = true;
boolean isEncrypted = false;
MessageTransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, version, 0, recipient, 0, null, data, isText, isEncrypted);
MessageTransaction messageTransaction = new MessageTransaction(repository, messageTransactionData);
return messageTransaction.hasValidReference();
}
private void testFeeNonce(boolean withFee, boolean withNonce, boolean isValid) throws DataException {
try (final Repository repository = RepositoryManager.getRepository()) {
TestAccount alice = Common.getTestAccount(repository, "alice");

Loading…
Cancel
Save