forked from Qortal/qortal
Reference fixes for MESSAGE transactions & tests to cover
This commit is contained in:
parent
e2e4555009
commit
faa6405d5f
@ -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
|
||||
|
@ -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…
x
Reference in New Issue
Block a user