mirror of
https://github.com/Qortal/qortal.git
synced 2025-07-23 04:36:50 +00:00
Allow MESSAGE transactions to have no recipient.
This allows on-chain messages to a group, including NO_GROUP / groupID zero. No-recipient messages cannot have an amount - where would it go? Changed MESSAGE serialization layout to add boolean indicating whether recipient is present. Changed MESSAGE serialization layout so assetID is after amount, and only present if amount is non-zero. Changed DB table structures to cover above. Added unit tests to cover above.
This commit is contained in:
154
src/test/java/org/qortal/test/MessageTests.java
Normal file
154
src/test/java/org/qortal/test/MessageTests.java
Normal file
@@ -0,0 +1,154 @@
|
||||
package org.qortal.test;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.qortal.asset.Asset;
|
||||
import org.qortal.data.transaction.MessageTransactionData;
|
||||
import org.qortal.data.transaction.TransactionData;
|
||||
import org.qortal.group.Group;
|
||||
import org.qortal.group.Group.ApprovalThreshold;
|
||||
import org.qortal.repository.DataException;
|
||||
import org.qortal.repository.Repository;
|
||||
import org.qortal.repository.RepositoryManager;
|
||||
import org.qortal.test.common.BlockUtils;
|
||||
import org.qortal.test.common.Common;
|
||||
import org.qortal.test.common.GroupUtils;
|
||||
import org.qortal.test.common.TestAccount;
|
||||
import org.qortal.test.common.TransactionUtils;
|
||||
import org.qortal.test.common.transaction.TestTransaction;
|
||||
import org.qortal.transaction.MessageTransaction;
|
||||
import org.qortal.transaction.Transaction;
|
||||
import org.qortal.transaction.Transaction.TransactionType;
|
||||
import org.qortal.transaction.Transaction.ValidationResult;
|
||||
import org.qortal.transform.TransformationException;
|
||||
import org.qortal.transform.transaction.MessageTransactionTransformer;
|
||||
import org.qortal.transform.transaction.TransactionTransformer;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class MessageTests extends Common {
|
||||
|
||||
private static final int version = 3;
|
||||
private static final String recipient = Common.getTestAccount(null, "bob").getAddress();
|
||||
|
||||
|
||||
@Before
|
||||
public void beforeTest() throws DataException {
|
||||
Common.useDefaultSettings();
|
||||
}
|
||||
|
||||
@After
|
||||
public void afterTest() throws DataException {
|
||||
Common.orphanCheck();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validityTests() throws DataException {
|
||||
// with recipient, with amount
|
||||
assertTrue(isValid(Group.NO_GROUP, recipient, 123L, Asset.QORT));
|
||||
|
||||
// with recipient, no amount
|
||||
assertTrue(isValid(Group.NO_GROUP, recipient, 0L, null));
|
||||
|
||||
// no recipient (message to group), no amount
|
||||
assertTrue(isValid(Group.NO_GROUP, null, 0L, null));
|
||||
|
||||
// can't have amount if no recipient!
|
||||
assertFalse(isValid(Group.NO_GROUP, null, 123L, Asset.QORT));
|
||||
|
||||
// Alice is part of group 1
|
||||
assertTrue(isValid(1, null, 0L, null));
|
||||
|
||||
int newGroupId;
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
newGroupId = GroupUtils.createGroup(repository, "chloe", "non-alice-group", false, ApprovalThreshold.ONE, 10, 1440);
|
||||
}
|
||||
|
||||
// Alice is not part of new group
|
||||
assertFalse(isValid(newGroupId, null, 0L, null));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withRecipentNoAmount() throws DataException {
|
||||
testMessage(Group.NO_GROUP, recipient, 0L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withRecipentWithAmount() throws DataException {
|
||||
testMessage(Group.NO_GROUP, recipient, 123L, Asset.QORT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noRecipentNoAmount() throws DataException {
|
||||
testMessage(Group.NO_GROUP, null, 0L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noRecipentNoAmountWithGroup() throws DataException {
|
||||
testMessage(1, null, 0L, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void serializationTests() throws DataException, TransformationException {
|
||||
// with recipient, with amount
|
||||
testSerialization(recipient, 123L, Asset.QORT);
|
||||
|
||||
// with recipient, no amount
|
||||
testSerialization(recipient, 0L, null);
|
||||
|
||||
// no recipient (message to group), no amount
|
||||
testSerialization(null, 0L, null);
|
||||
}
|
||||
|
||||
private boolean isValid(int txGroupId, String recipient, long amount, Long assetId) throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
MessageTransactionData transactionData = new MessageTransactionData(TestTransaction.generateBase(alice, txGroupId),
|
||||
version, recipient, amount, assetId, new byte[1], false, false);
|
||||
|
||||
Transaction transaction = new MessageTransaction(repository, transactionData);
|
||||
|
||||
return transaction.isValidUnconfirmed() == ValidationResult.OK;
|
||||
}
|
||||
}
|
||||
|
||||
private void testMessage(int txGroupId, String recipient, long amount, Long assetId) throws DataException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
MessageTransactionData transactionData = new MessageTransactionData(TestTransaction.generateBase(alice, txGroupId),
|
||||
version, recipient, amount, assetId, new byte[1], false, false);
|
||||
|
||||
TransactionUtils.signAndMint(repository, transactionData, alice);
|
||||
|
||||
BlockUtils.orphanLastBlock(repository);
|
||||
}
|
||||
}
|
||||
|
||||
private void testSerialization(String recipient, long amount, Long assetId) throws DataException, TransformationException {
|
||||
try (final Repository repository = RepositoryManager.getRepository()) {
|
||||
TestAccount alice = Common.getTestAccount(repository, "alice");
|
||||
|
||||
MessageTransactionData expectedTransactionData = new MessageTransactionData(TestTransaction.generateBase(alice),
|
||||
version, recipient, amount, assetId, new byte[1], false, false);
|
||||
|
||||
Transaction transaction = new MessageTransaction(repository, expectedTransactionData);
|
||||
transaction.sign(alice);
|
||||
|
||||
MessageTransactionTransformer.getDataLength(expectedTransactionData);
|
||||
byte[] transactionBytes = MessageTransactionTransformer.toBytes(expectedTransactionData);
|
||||
|
||||
TransactionData transactionData = TransactionTransformer.fromBytes(transactionBytes);
|
||||
assertEquals(TransactionType.MESSAGE, transactionData.getType());
|
||||
|
||||
MessageTransactionData actualTransactionData = (MessageTransactionData) transactionData;
|
||||
|
||||
assertEquals(expectedTransactionData.getRecipient(), actualTransactionData.getRecipient());
|
||||
assertEquals(expectedTransactionData.getAmount(), actualTransactionData.getAmount());
|
||||
assertEquals(expectedTransactionData.getAssetId(), actualTransactionData.getAssetId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -474,9 +474,10 @@ public class AtTests extends Common {
|
||||
|
||||
Long fee = null;
|
||||
long amount = 0;
|
||||
Long assetId = null; // because amount is zero
|
||||
|
||||
BaseTransactionData baseTransactionData = new BaseTransactionData(txTimestamp, Group.NO_GROUP, lastReference, sender.getPublicKey(), fee, null);
|
||||
TransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, 4, recipient, Asset.QORT, amount, data, false, false);
|
||||
TransactionData messageTransactionData = new MessageTransactionData(baseTransactionData, 4, recipient, amount, assetId, data, false, false);
|
||||
|
||||
MessageTransaction messageTransaction = new MessageTransaction(repository, messageTransactionData);
|
||||
|
||||
|
@@ -19,7 +19,7 @@ public class MessageTestTransaction extends TestTransaction {
|
||||
final boolean isText = true;
|
||||
final boolean isEncrypted = false;
|
||||
|
||||
return new MessageTransactionData(generateBase(account), version, recipient, assetId, amount, data, isText, isEncrypted);
|
||||
return new MessageTransactionData(generateBase(account), version, recipient, amount, assetId, data, isText, isEncrypted);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -12,8 +12,12 @@ public abstract class TestTransaction {
|
||||
|
||||
protected static final Random random = new Random();
|
||||
|
||||
public static BaseTransactionData generateBase(PrivateKeyAccount account, int txGroupId) throws DataException {
|
||||
return new BaseTransactionData(System.currentTimeMillis(), txGroupId, account.getLastReference(), account.getPublicKey(), BlockChain.getInstance().getUnitFee(), null);
|
||||
}
|
||||
|
||||
public static BaseTransactionData generateBase(PrivateKeyAccount account) throws DataException {
|
||||
return new BaseTransactionData(System.currentTimeMillis(), Group.NO_GROUP, account.getLastReference(), account.getPublicKey(), BlockChain.getInstance().getUnitFee(), null);
|
||||
return generateBase(account, Group.NO_GROUP);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user