forked from Qortal/qortal
AT transactions now either have null message or null amount&assetId.
AT transaction transformer changed to refuse to deserialize AT transactions, as they should never appear on the wire. Ditto for GENESIS transactions.
This commit is contained in:
parent
e1f3b9a7a3
commit
233ace23de
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -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)
|
||||
|
@ -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()));
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user