diff --git a/src/main/java/org/qortal/at/QortalATAPI.java b/src/main/java/org/qortal/at/QortalATAPI.java index c01f9c3b..e9bc91c1 100644 --- a/src/main/java/org/qortal/at/QortalATAPI.java +++ b/src/main/java/org/qortal/at/QortalATAPI.java @@ -376,7 +376,7 @@ public class QortalATAPI extends API { BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, NullAccount.PUBLIC_KEY, 0L, null); ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(), - recipient.getAddress(), amount, this.atData.getAssetId(), new byte[0]); + recipient.getAddress(), amount, this.atData.getAssetId()); AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData); // Add to our transactions @@ -393,7 +393,7 @@ public class QortalATAPI extends API { BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, NullAccount.PUBLIC_KEY, 0L, null); ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(), - recipient.getAddress(), 0L, this.atData.getAssetId(), message); + recipient.getAddress(), message); AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData); // Add to our transactions @@ -422,7 +422,7 @@ public class QortalATAPI extends API { BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, reference, NullAccount.PUBLIC_KEY, 0L, null); ATTransactionData atTransactionData = new ATTransactionData(baseTransactionData, this.atData.getATAddress(), - creator.getAddress(), finalBalance, this.atData.getAssetId(), new byte[0]); + creator.getAddress(), finalBalance, this.atData.getAssetId()); AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData); // Add to our transactions diff --git a/src/main/java/org/qortal/data/transaction/ATTransactionData.java b/src/main/java/org/qortal/data/transaction/ATTransactionData.java index 92469eaf..5d5d640b 100644 --- a/src/main/java/org/qortal/data/transaction/ATTransactionData.java +++ b/src/main/java/org/qortal/data/transaction/ATTransactionData.java @@ -29,6 +29,7 @@ public class ATTransactionData extends TransactionData { // Not always present private Long assetId; + // Not always present private byte[] message; // Constructors @@ -42,7 +43,7 @@ public class ATTransactionData extends TransactionData { this.creatorPublicKey = NullAccount.PUBLIC_KEY; } - /** From repository */ + /** Constructing from repository */ public ATTransactionData(BaseTransactionData baseTransactionData, String atAddress, String recipient, Long amount, Long assetId, byte[] message) { super(TransactionType.AT, baseTransactionData); @@ -54,6 +55,16 @@ public class ATTransactionData extends TransactionData { this.message = message; } + /** Constructing a new MESSAGE-type AT transaction */ + public ATTransactionData(BaseTransactionData baseTransactionData, String atAddress, String recipient, byte[] message) { + this(baseTransactionData, atAddress, recipient, null, null, message); + } + + /** Constructing a new PAYMENT-type AT transaction */ + public ATTransactionData(BaseTransactionData baseTransactionData, String atAddress, String recipient, long amount, long assetId) { + this(baseTransactionData, atAddress, recipient, amount, assetId, null); + } + // Getters/Setters public String getATAddress() { diff --git a/src/main/java/org/qortal/transaction/AtTransaction.java b/src/main/java/org/qortal/transaction/AtTransaction.java index 2c086de3..89267072 100644 --- a/src/main/java/org/qortal/transaction/AtTransaction.java +++ b/src/main/java/org/qortal/transaction/AtTransaction.java @@ -87,27 +87,27 @@ public class AtTransaction extends Transaction { return ValidationResult.INVALID_ADDRESS; Long amount = this.atTransactionData.getAmount(); + Long assetId = this.atTransactionData.getAssetId(); byte[] message = this.atTransactionData.getMessage(); - // We can only have either message or amount - boolean amountIsNull = amount == null; - boolean messageIsEmpty = message == null || message.length == 0; + boolean hasPayment = amount != null && assetId != null; + boolean hasMessage = message != null; // empty message OK - if ((messageIsEmpty && amountIsNull) || (!messageIsEmpty && !amountIsNull)) + // We can only have either message or payment, not both, nor neither + if ((hasMessage && hasPayment) || (!hasMessage && !hasPayment)) return ValidationResult.INVALID_AT_TRANSACTION; - if (!messageIsEmpty && message.length > MAX_DATA_SIZE) + if (hasMessage && message.length > MAX_DATA_SIZE) return ValidationResult.INVALID_DATA_LENGTH; // If we have no payment then we're done - if (amountIsNull) + if (!hasPayment) return ValidationResult.OK; // Check amount is zero or positive if (amount < 0) return ValidationResult.NEGATIVE_AMOUNT; - long assetId = this.atTransactionData.getAssetId(); AssetData assetData = this.repository.getAssetRepository().fromAssetId(assetId); // Check asset even exists if (assetData == null) diff --git a/src/main/java/org/qortal/transform/transaction/AtTransactionTransformer.java b/src/main/java/org/qortal/transform/transaction/AtTransactionTransformer.java index d9c1a586..6b3c93f0 100644 --- a/src/main/java/org/qortal/transform/transaction/AtTransactionTransformer.java +++ b/src/main/java/org/qortal/transform/transaction/AtTransactionTransformer.java @@ -14,25 +14,18 @@ import com.google.common.primitives.Longs; public class AtTransactionTransformer extends TransactionTransformer { - private static final int SENDER_LENGTH = ADDRESS_LENGTH; - private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH; - private static final int DATA_SIZE_LENGTH = INT_LENGTH; - - private static final int EXTRAS_LENGTH = SENDER_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + ASSET_ID_LENGTH + DATA_SIZE_LENGTH; - protected static final TransactionLayout layout = null; // Property lengths public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { - throw new TransformationException("Serialized AT Transactions should not exist!"); + throw new TransformationException("Serialized AT transactions should not exist!"); } public static int getDataLength(TransactionData transactionData) throws TransformationException { - ATTransactionData atTransactionData = (ATTransactionData) transactionData; - - return getBaseLength(transactionData) + EXTRAS_LENGTH + atTransactionData.getMessage().length; + throw new TransformationException("Serialized AT transactions should not exist!"); } + // Used for generating fake transaction signatures public static byte[] toBytes(TransactionData transactionData) throws TransformationException { try { ATTransactionData atTransactionData = (ATTransactionData) transactionData; @@ -47,18 +40,16 @@ public class AtTransactionTransformer extends TransactionTransformer { Serialization.serializeAddress(bytes, atTransactionData.getRecipient()); - // Only emit amount if greater than zero (safer than checking assetId) - if (atTransactionData.getAmount() > 0) { - bytes.write(Longs.toByteArray(atTransactionData.getAmount())); - bytes.write(Longs.toByteArray(atTransactionData.getAssetId())); - } - byte[] message = atTransactionData.getMessage(); - if (message.length > 0) { + + if (message != null) { + // MESSAGE-type bytes.write(Ints.toByteArray(message.length)); bytes.write(message); } else { - bytes.write(Ints.toByteArray(0)); + // PAYMENT-type + bytes.write(Longs.toByteArray(atTransactionData.getAssetId())); + bytes.write(Longs.toByteArray(atTransactionData.getAmount())); } bytes.write(Longs.toByteArray(atTransactionData.getFee())); diff --git a/src/main/java/org/qortal/transform/transaction/GenesisTransactionTransformer.java b/src/main/java/org/qortal/transform/transaction/GenesisTransactionTransformer.java index 89f7cf16..41348b79 100644 --- a/src/main/java/org/qortal/transform/transaction/GenesisTransactionTransformer.java +++ b/src/main/java/org/qortal/transform/transaction/GenesisTransactionTransformer.java @@ -4,12 +4,8 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.nio.ByteBuffer; -import org.qortal.account.NullAccount; -import org.qortal.data.transaction.BaseTransactionData; import org.qortal.data.transaction.GenesisTransactionData; import org.qortal.data.transaction.TransactionData; -import org.qortal.group.Group; -import org.qortal.transaction.Transaction.TransactionType; import org.qortal.transform.TransformationException; import org.qortal.utils.Serialization; @@ -18,43 +14,17 @@ import com.google.common.primitives.Longs; public class GenesisTransactionTransformer extends TransactionTransformer { - // Note that Genesis transactions don't require reference, fee or signature - - // Property lengths - private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH; - - private static final int TOTAL_LENGTH = TYPE_LENGTH + TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + ASSET_ID_LENGTH; - - protected static final TransactionLayout layout; - - static { - layout = new TransactionLayout(); - layout.add("txType: " + TransactionType.GENESIS.valueString, TransformationType.INT); - layout.add("timestamp", TransformationType.TIMESTAMP); - layout.add("recipient", TransformationType.ADDRESS); - layout.add("amount", TransformationType.AMOUNT); - layout.add("asset ID", TransformationType.LONG); - layout.add("signature", TransformationType.SIGNATURE); - } + protected static final TransactionLayout layout = null; public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { - long timestamp = byteBuffer.getLong(); - - String recipient = Serialization.deserializeAddress(byteBuffer); - - long amount = byteBuffer.getLong(); - - long assetId = byteBuffer.getLong(); - - BaseTransactionData baseTransactionData = new BaseTransactionData(timestamp, Group.NO_GROUP, null, NullAccount.PUBLIC_KEY, 0L, null); - - return new GenesisTransactionData(baseTransactionData, recipient, amount, assetId); + throw new TransformationException("Serialized GENESIS transactions should not exist!"); } public static int getDataLength(TransactionData transactionData) throws TransformationException { - return TOTAL_LENGTH; + throw new TransformationException("Serialized GENESIS transactions should not exist!"); } + // Used when generating fake signatures for genesis block public static byte[] toBytes(TransactionData transactionData) throws TransformationException { try { GenesisTransactionData genesisTransactionData = (GenesisTransactionData) transactionData;