diff --git a/src/main/java/org/qora/api/resource/AssetsResource.java b/src/main/java/org/qora/api/resource/AssetsResource.java index 840f6e35..060df6bd 100644 --- a/src/main/java/org/qora/api/resource/AssetsResource.java +++ b/src/main/java/org/qora/api/resource/AssetsResource.java @@ -32,8 +32,8 @@ import org.qora.data.account.AccountBalanceData; import org.qora.data.asset.AssetData; import org.qora.data.asset.OrderData; import org.qora.data.asset.TradeData; -import org.qora.data.transaction.CancelOrderTransactionData; -import org.qora.data.transaction.CreateOrderTransactionData; +import org.qora.data.transaction.CancelAssetOrderTransactionData; +import org.qora.data.transaction.CreateAssetOrderTransactionData; import org.qora.data.transaction.IssueAssetTransactionData; import org.qora.repository.DataException; import org.qora.repository.Repository; @@ -41,8 +41,8 @@ import org.qora.repository.RepositoryManager; import org.qora.transaction.Transaction; import org.qora.transaction.Transaction.ValidationResult; import org.qora.transform.TransformationException; -import org.qora.transform.transaction.CancelOrderTransactionTransformer; -import org.qora.transform.transaction.CreateOrderTransactionTransformer; +import org.qora.transform.transaction.CancelAssetOrderTransactionTransformer; +import org.qora.transform.transaction.CreateAssetOrderTransactionTransformer; import org.qora.transform.transaction.IssueAssetTransactionTransformer; import org.qora.utils.Base58; @@ -241,7 +241,7 @@ public class AssetsResource { required = true, content = @Content( mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = CancelOrderTransactionData.class) + schema = @Schema(implementation = CancelAssetOrderTransactionData.class) ) ), responses = { @@ -257,7 +257,7 @@ public class AssetsResource { } ) @ApiErrors({ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE, ApiError.TRANSACTION_INVALID}) - public String cancelOrder(CancelOrderTransactionData transactionData) { + public String cancelOrder(CancelAssetOrderTransactionData transactionData) { try (final Repository repository = RepositoryManager.getRepository()) { Transaction transaction = Transaction.fromData(repository, transactionData); @@ -265,7 +265,7 @@ public class AssetsResource { if (result != ValidationResult.OK) throw TransactionsResource.createTransactionInvalidException(request, result); - byte[] bytes = CancelOrderTransactionTransformer.toBytes(transactionData); + byte[] bytes = CancelAssetOrderTransactionTransformer.toBytes(transactionData); return Base58.encode(bytes); } catch (TransformationException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e); @@ -323,7 +323,7 @@ public class AssetsResource { required = true, content = @Content( mediaType = MediaType.APPLICATION_JSON, - schema = @Schema(implementation = CreateOrderTransactionData.class) + schema = @Schema(implementation = CreateAssetOrderTransactionData.class) ) ), responses = { @@ -339,7 +339,7 @@ public class AssetsResource { } ) @ApiErrors({ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE, ApiError.TRANSACTION_INVALID}) - public String createOrder(CreateOrderTransactionData transactionData) { + public String createOrder(CreateAssetOrderTransactionData transactionData) { try (final Repository repository = RepositoryManager.getRepository()) { Transaction transaction = Transaction.fromData(repository, transactionData); @@ -347,7 +347,7 @@ public class AssetsResource { if (result != ValidationResult.OK) throw TransactionsResource.createTransactionInvalidException(request, result); - byte[] bytes = CreateOrderTransactionTransformer.toBytes(transactionData); + byte[] bytes = CreateAssetOrderTransactionTransformer.toBytes(transactionData); return Base58.encode(bytes); } catch (TransformationException e) { throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e); diff --git a/src/main/java/org/qora/api/resource/UtilsResource.java b/src/main/java/org/qora/api/resource/UtilsResource.java index f210e78f..367a03fa 100644 --- a/src/main/java/org/qora/api/resource/UtilsResource.java +++ b/src/main/java/org/qora/api/resource/UtilsResource.java @@ -1,6 +1,7 @@ package org.qora.api.resource; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.parameters.RequestBody; @@ -10,6 +11,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import java.security.SecureRandom; import java.util.Arrays; import java.util.Base64; +import java.util.List; import java.util.UUID; import javax.servlet.http.HttpServletRequest; @@ -27,6 +29,9 @@ import org.qora.api.ApiError; import org.qora.api.ApiErrors; import org.qora.api.ApiExceptionFactory; import org.qora.crypto.Crypto; +import org.qora.transaction.Transaction.TransactionType; +import org.qora.transform.transaction.TransactionTransformer; +import org.qora.transform.transaction.TransactionTransformer.Transformation; import org.qora.utils.BIP39; import org.qora.utils.Base58; import org.qora.utils.NTP; @@ -37,7 +42,7 @@ import com.google.common.primitives.Longs; @Path("/utils") @Produces({ - MediaType.TEXT_PLAIN + MediaType.TEXT_PLAIN, MediaType.APPLICATION_JSON }) @Tag( name = "Utilities" @@ -372,4 +377,22 @@ public class UtilsResource { return NTP.getTime(); } + @GET + @Path("/layout/{txtype}") + @Operation( + summary = "Returns raw transaction layout based on transaction type", + description = "Components are returned in sequential order used to build transaction. Components marked with * are part of a repeatable group. For example, multiple payments within a MULTI-PAYMENT transaction.", + responses = { + @ApiResponse( + content = @Content( + mediaType = MediaType.APPLICATION_JSON, + array = @ArraySchema(schema = @Schema( implementation = Transformation.class )) + ) + ) + } + ) + public List getLayout(@PathParam("txtype") TransactionType txType) { + return TransactionTransformer.getLayoutByTxType(txType); + } + } \ No newline at end of file diff --git a/src/main/java/org/qora/at/AT.java b/src/main/java/org/qora/at/AT.java index 979145a7..06706074 100644 --- a/src/main/java/org/qora/at/AT.java +++ b/src/main/java/org/qora/at/AT.java @@ -9,7 +9,7 @@ import org.qora.asset.Asset; import org.qora.crypto.Crypto; import org.qora.data.at.ATData; import org.qora.data.at.ATStateData; -import org.qora.data.transaction.DeployATTransactionData; +import org.qora.data.transaction.DeployAtTransactionData; import org.qora.repository.ATRepository; import org.qora.repository.DataException; import org.qora.repository.Repository; @@ -35,7 +35,7 @@ public class AT { } /** Constructs AT-handling object when deploying AT */ - public AT(Repository repository, DeployATTransactionData deployATTransactionData) throws DataException { + public AT(Repository repository, DeployAtTransactionData deployATTransactionData) throws DataException { this.repository = repository; String atAddress = deployATTransactionData.getATAddress(); diff --git a/src/main/java/org/qora/data/transaction/CancelOrderTransactionData.java b/src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java similarity index 80% rename from src/main/java/org/qora/data/transaction/CancelOrderTransactionData.java rename to src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java index b7175885..1d1021ef 100644 --- a/src/main/java/org/qora/data/transaction/CancelOrderTransactionData.java +++ b/src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java @@ -14,7 +14,7 @@ import io.swagger.v3.oas.annotations.media.Schema; // All properties to be converted to JSON via JAX-RS @XmlAccessorType(XmlAccessType.FIELD) @Schema(allOf = { TransactionData.class }) -public class CancelOrderTransactionData extends TransactionData { +public class CancelAssetOrderTransactionData extends TransactionData { // Properties @Schema(description = "order ID to cancel", example = "real_order_ID_in_base58") @@ -23,17 +23,17 @@ public class CancelOrderTransactionData extends TransactionData { // Constructors // For JAX-RS - protected CancelOrderTransactionData() { + protected CancelAssetOrderTransactionData() { super(TransactionType.CANCEL_ASSET_ORDER); } - public CancelOrderTransactionData(byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { + public CancelAssetOrderTransactionData(byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { super(Transaction.TransactionType.CANCEL_ASSET_ORDER, fee, creatorPublicKey, timestamp, reference, signature); this.orderId = orderId; } - public CancelOrderTransactionData(byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, long timestamp, byte[] reference) { + public CancelAssetOrderTransactionData(byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, long timestamp, byte[] reference) { this(creatorPublicKey, orderId, fee, timestamp, reference, null); } diff --git a/src/main/java/org/qora/data/transaction/CreateOrderTransactionData.java b/src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java similarity index 84% rename from src/main/java/org/qora/data/transaction/CreateOrderTransactionData.java rename to src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java index 83c4417a..ef232e9b 100644 --- a/src/main/java/org/qora/data/transaction/CreateOrderTransactionData.java +++ b/src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java @@ -13,7 +13,7 @@ import io.swagger.v3.oas.annotations.media.Schema; // All properties to be converted to JSON via JAX-RS @XmlAccessorType(XmlAccessType.FIELD) @Schema(allOf = { TransactionData.class }) -public class CreateOrderTransactionData extends TransactionData { +public class CreateAssetOrderTransactionData extends TransactionData { // Properties @Schema(description = "ID of asset on offer to give by order creator", example = "1") @@ -28,11 +28,11 @@ public class CreateOrderTransactionData extends TransactionData { // Constructors // For JAX-RS - protected CreateOrderTransactionData() { + protected CreateAssetOrderTransactionData() { super(TransactionType.CREATE_ASSET_ORDER); } - public CreateOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, + public CreateAssetOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { super(TransactionType.CREATE_ASSET_ORDER, fee, creatorPublicKey, timestamp, reference, signature); @@ -42,7 +42,7 @@ public class CreateOrderTransactionData extends TransactionData { this.price = price; } - public CreateOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, + public CreateAssetOrderTransactionData(byte[] creatorPublicKey, long haveAssetId, long wantAssetId, BigDecimal amount, BigDecimal price, BigDecimal fee, long timestamp, byte[] reference) { this(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, null); } diff --git a/src/main/java/org/qora/data/transaction/DeployATTransactionData.java b/src/main/java/org/qora/data/transaction/DeployAtTransactionData.java similarity index 88% rename from src/main/java/org/qora/data/transaction/DeployATTransactionData.java rename to src/main/java/org/qora/data/transaction/DeployAtTransactionData.java index c32bf183..ebda409c 100644 --- a/src/main/java/org/qora/data/transaction/DeployATTransactionData.java +++ b/src/main/java/org/qora/data/transaction/DeployAtTransactionData.java @@ -12,7 +12,7 @@ import io.swagger.v3.oas.annotations.media.Schema; // All properties to be converted to JSON via JAX-RS @XmlAccessorType(XmlAccessType.FIELD) @Schema(allOf = { TransactionData.class }) -public class DeployATTransactionData extends TransactionData { +public class DeployAtTransactionData extends TransactionData { // Properties private String name; @@ -27,10 +27,10 @@ public class DeployATTransactionData extends TransactionData { // Constructors // For JAX-RS - protected DeployATTransactionData() { + protected DeployAtTransactionData() { } - public DeployATTransactionData(String ATAddress, byte[] creatorPublicKey, String name, String description, String ATType, String tags, byte[] creationBytes, + public DeployAtTransactionData(String ATAddress, byte[] creatorPublicKey, String name, String description, String ATType, String tags, byte[] creationBytes, BigDecimal amount, long assetId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { super(TransactionType.DEPLOY_AT, fee, creatorPublicKey, timestamp, reference, signature); @@ -44,12 +44,12 @@ public class DeployATTransactionData extends TransactionData { this.ATAddress = ATAddress; } - public DeployATTransactionData(byte[] creatorPublicKey, String name, String description, String ATType, String tags, byte[] creationBytes, + public DeployAtTransactionData(byte[] creatorPublicKey, String name, String description, String ATType, String tags, byte[] creationBytes, BigDecimal amount, long assetId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { this(null, creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp, reference, signature); } - public DeployATTransactionData(byte[] creatorPublicKey, String name, String description, String ATType, String tags, byte[] creationBytes, + public DeployAtTransactionData(byte[] creatorPublicKey, String name, String description, String ATType, String tags, byte[] creationBytes, BigDecimal amount, long assetId, BigDecimal fee, long timestamp, byte[] reference) { this(null, creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp, reference, null); } diff --git a/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java b/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java index f24a19a4..f63f52c7 100644 --- a/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java +++ b/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java @@ -27,7 +27,7 @@ public class MultiPaymentTransactionData extends TransactionData { } public MultiPaymentTransactionData(byte[] senderPublicKey, List payments, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) { - super(Transaction.TransactionType.MULTIPAYMENT, fee, senderPublicKey, timestamp, reference, signature); + super(Transaction.TransactionType.MULTI_PAYMENT, fee, senderPublicKey, timestamp, reference, signature); this.senderPublicKey = senderPublicKey; this.payments = payments; diff --git a/src/main/java/org/qora/data/transaction/TransactionData.java b/src/main/java/org/qora/data/transaction/TransactionData.java index 1edfb061..3d953dde 100644 --- a/src/main/java/org/qora/data/transaction/TransactionData.java +++ b/src/main/java/org/qora/data/transaction/TransactionData.java @@ -31,8 +31,8 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode; SellNameTransactionData.class, CancelSellNameTransactionData.class, BuyNameTransactionData.class, CreatePollTransactionData.class, VoteOnPollTransactionData.class, ArbitraryTransactionData.class, IssueAssetTransactionData.class, TransferAssetTransactionData.class, - CreateOrderTransactionData.class, CancelOrderTransactionData.class, - MultiPaymentTransactionData.class, DeployATTransactionData.class, MessageTransactionData.class, ATTransactionData.class, + CreateAssetOrderTransactionData.class, CancelAssetOrderTransactionData.class, + MultiPaymentTransactionData.class, DeployAtTransactionData.class, MessageTransactionData.class, ATTransactionData.class, CreateGroupTransactionData.class, UpdateGroupTransactionData.class, AddGroupAdminTransactionData.class, RemoveGroupAdminTransactionData.class, GroupBanTransactionData.class, CancelGroupBanTransactionData.class, diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java index 7b9d8fba..6d023cdc 100644 --- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelOrderTransactionRepository.java @@ -4,7 +4,7 @@ import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; -import org.qora.data.transaction.CancelOrderTransactionData; +import org.qora.data.transaction.CancelAssetOrderTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.repository.DataException; import org.qora.repository.hsqldb.HSQLDBRepository; @@ -23,7 +23,7 @@ public class HSQLDBCancelOrderTransactionRepository extends HSQLDBTransactionRep byte[] assetOrderId = resultSet.getBytes(1); - return new CancelOrderTransactionData(creatorPublicKey, assetOrderId, fee, timestamp, reference, signature); + return new CancelAssetOrderTransactionData(creatorPublicKey, assetOrderId, fee, timestamp, reference, signature); } catch (SQLException e) { throw new DataException("Unable to fetch cancel order transaction from repository", e); } @@ -31,7 +31,7 @@ public class HSQLDBCancelOrderTransactionRepository extends HSQLDBTransactionRep @Override public void save(TransactionData transactionData) throws DataException { - CancelOrderTransactionData cancelOrderTransactionData = (CancelOrderTransactionData) transactionData; + CancelAssetOrderTransactionData cancelOrderTransactionData = (CancelAssetOrderTransactionData) transactionData; HSQLDBSaver saveHelper = new HSQLDBSaver("CancelAssetOrderTransactions"); diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java index a4b903da..f38b45c5 100644 --- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateOrderTransactionRepository.java @@ -4,7 +4,7 @@ import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; -import org.qora.data.transaction.CreateOrderTransactionData; +import org.qora.data.transaction.CreateAssetOrderTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.repository.DataException; import org.qora.repository.hsqldb.HSQLDBRepository; @@ -27,7 +27,7 @@ public class HSQLDBCreateOrderTransactionRepository extends HSQLDBTransactionRep long wantAssetId = resultSet.getLong(3); BigDecimal price = resultSet.getBigDecimal(4); - return new CreateOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature); + return new CreateAssetOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature); } catch (SQLException e) { throw new DataException("Unable to fetch create order transaction from repository", e); } @@ -35,7 +35,7 @@ public class HSQLDBCreateOrderTransactionRepository extends HSQLDBTransactionRep @Override public void save(TransactionData transactionData) throws DataException { - CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + CreateAssetOrderTransactionData createOrderTransactionData = (CreateAssetOrderTransactionData) transactionData; HSQLDBSaver saveHelper = new HSQLDBSaver("CreateAssetOrderTransactions"); diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java index d8ea3526..a9e51e3a 100644 --- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBDeployATTransactionRepository.java @@ -4,7 +4,7 @@ import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; -import org.qora.data.transaction.DeployATTransactionData; +import org.qora.data.transaction.DeployAtTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.repository.DataException; import org.qora.repository.hsqldb.HSQLDBRepository; @@ -36,7 +36,7 @@ public class HSQLDBDeployATTransactionRepository extends HSQLDBTransactionReposi if (resultSet.wasNull()) ATAddress = null; - return new DeployATTransactionData(ATAddress, creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp, + return new DeployAtTransactionData(ATAddress, creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp, reference, signature); } catch (SQLException e) { throw new DataException("Unable to fetch deploy AT transaction from repository", e); @@ -45,7 +45,7 @@ public class HSQLDBDeployATTransactionRepository extends HSQLDBTransactionReposi @Override public void save(TransactionData transactionData) throws DataException { - DeployATTransactionData deployATTransactionData = (DeployATTransactionData) transactionData; + DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData; HSQLDBSaver saveHelper = new HSQLDBSaver("DeployATTransactions"); diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java index d1402927..569ce8a4 100644 --- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java @@ -1,5 +1,8 @@ package org.qora.repository.hsqldb.transaction; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; @@ -22,73 +25,40 @@ public class HSQLDBTransactionRepository implements TransactionRepository { private static final Logger LOGGER = LogManager.getLogger(HSQLDBTransactionRepository.class); + private HSQLDBTransactionRepository[] repositoryByTxType; protected HSQLDBRepository repository; - private HSQLDBGenesisTransactionRepository genesisTransactionRepository; - private HSQLDBPaymentTransactionRepository paymentTransactionRepository; - private HSQLDBRegisterNameTransactionRepository registerNameTransactionRepository; - private HSQLDBUpdateNameTransactionRepository updateNameTransactionRepository; - private HSQLDBSellNameTransactionRepository sellNameTransactionRepository; - private HSQLDBCancelSellNameTransactionRepository cancelSellNameTransactionRepository; - private HSQLDBBuyNameTransactionRepository buyNameTransactionRepository; - private HSQLDBCreatePollTransactionRepository createPollTransactionRepository; - private HSQLDBVoteOnPollTransactionRepository voteOnPollTransactionRepository; - private HSQLDBArbitraryTransactionRepository arbitraryTransactionRepository; - private HSQLDBIssueAssetTransactionRepository issueAssetTransactionRepository; - private HSQLDBTransferAssetTransactionRepository transferAssetTransactionRepository; - private HSQLDBCreateOrderTransactionRepository createOrderTransactionRepository; - private HSQLDBCancelOrderTransactionRepository cancelOrderTransactionRepository; - private HSQLDBMultiPaymentTransactionRepository multiPaymentTransactionRepository; - private HSQLDBDeployATTransactionRepository deployATTransactionRepository; - private HSQLDBMessageTransactionRepository messageTransactionRepository; - private HSQLDBATTransactionRepository atTransactionRepository; - private HSQLDBCreateGroupTransactionRepository createGroupTransactionRepository; - private HSQLDBUpdateGroupTransactionRepository updateGroupTransactionRepository; - private HSQLDBAddGroupAdminTransactionRepository addGroupAdminTransactionRepository; - private HSQLDBRemoveGroupAdminTransactionRepository removeGroupAdminTransactionRepository; - private HSQLDBGroupBanTransactionRepository groupBanTransactionRepository; - private HSQLDBCancelGroupBanTransactionRepository groupUnbanTransactionRepository; - private HSQLDBGroupKickTransactionRepository groupKickTransactionRepository; - private HSQLDBGroupInviteTransactionRepository groupInviteTransactionRepository; - private HSQLDBCancelGroupInviteTransactionRepository cancelGroupInviteTransactionRepository; - private HSQLDBJoinGroupTransactionRepository joinGroupTransactionRepository; - private HSQLDBLeaveGroupTransactionRepository leaveGroupTransactionRepository; public HSQLDBTransactionRepository(HSQLDBRepository repository) { this.repository = repository; - this.genesisTransactionRepository = new HSQLDBGenesisTransactionRepository(repository); - this.paymentTransactionRepository = new HSQLDBPaymentTransactionRepository(repository); - this.registerNameTransactionRepository = new HSQLDBRegisterNameTransactionRepository(repository); - this.updateNameTransactionRepository = new HSQLDBUpdateNameTransactionRepository(repository); - this.sellNameTransactionRepository = new HSQLDBSellNameTransactionRepository(repository); - this.cancelSellNameTransactionRepository = new HSQLDBCancelSellNameTransactionRepository(repository); - this.buyNameTransactionRepository = new HSQLDBBuyNameTransactionRepository(repository); - this.createPollTransactionRepository = new HSQLDBCreatePollTransactionRepository(repository); - this.voteOnPollTransactionRepository = new HSQLDBVoteOnPollTransactionRepository(repository); - this.arbitraryTransactionRepository = new HSQLDBArbitraryTransactionRepository(repository); - this.issueAssetTransactionRepository = new HSQLDBIssueAssetTransactionRepository(repository); - this.transferAssetTransactionRepository = new HSQLDBTransferAssetTransactionRepository(repository); - this.createOrderTransactionRepository = new HSQLDBCreateOrderTransactionRepository(repository); - this.cancelOrderTransactionRepository = new HSQLDBCancelOrderTransactionRepository(repository); - this.multiPaymentTransactionRepository = new HSQLDBMultiPaymentTransactionRepository(repository); - this.deployATTransactionRepository = new HSQLDBDeployATTransactionRepository(repository); - this.messageTransactionRepository = new HSQLDBMessageTransactionRepository(repository); - this.atTransactionRepository = new HSQLDBATTransactionRepository(repository); - this.createGroupTransactionRepository = new HSQLDBCreateGroupTransactionRepository(repository); - this.updateGroupTransactionRepository = new HSQLDBUpdateGroupTransactionRepository(repository); - this.addGroupAdminTransactionRepository = new HSQLDBAddGroupAdminTransactionRepository(repository); - this.removeGroupAdminTransactionRepository = new HSQLDBRemoveGroupAdminTransactionRepository(repository); - this.groupBanTransactionRepository = new HSQLDBGroupBanTransactionRepository(repository); - this.groupUnbanTransactionRepository = new HSQLDBCancelGroupBanTransactionRepository(repository); - this.groupKickTransactionRepository = new HSQLDBGroupKickTransactionRepository(repository); - this.groupInviteTransactionRepository = new HSQLDBGroupInviteTransactionRepository(repository); - this.cancelGroupInviteTransactionRepository = new HSQLDBCancelGroupInviteTransactionRepository(repository); - this.joinGroupTransactionRepository = new HSQLDBJoinGroupTransactionRepository(repository); - this.leaveGroupTransactionRepository = new HSQLDBLeaveGroupTransactionRepository(repository); + + this.repositoryByTxType = new HSQLDBTransactionRepository[256]; + + for (TransactionType txType : TransactionType.values()) { + Class repositoryClass = getClassByTxType(txType); + if (repositoryClass == null) + continue; + + try { + Constructor constructor = repositoryClass.getConstructor(HSQLDBRepository.class); + HSQLDBTransactionRepository txRepository = (HSQLDBTransactionRepository) constructor.newInstance(repository); + this.repositoryByTxType[txType.value] = txRepository; + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) { + continue; + } + } } protected HSQLDBTransactionRepository() { } + private static Class getClassByTxType(TransactionType txType) { + try { + return Class.forName(String.join("", HSQLDBTransactionRepository.class.getPackage().getName(), ".", "HSQLDB", txType.className, "TransactionRepository")); + } catch (ClassNotFoundException e) { + return null; + } + } + @Override public TransactionData fromSignature(byte[] signature) throws DataException { try (ResultSet resultSet = this.repository.checkedExecute("SELECT type, reference, creator, creation, fee FROM Transactions WHERE signature = ?", @@ -155,96 +125,15 @@ public class HSQLDBTransactionRepository implements TransactionRepository { private TransactionData fromBase(TransactionType type, byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException { - switch (type) { - case GENESIS: - return this.genesisTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); + HSQLDBTransactionRepository txRepository = repositoryByTxType[type.value]; + if (txRepository == null) + throw new DataException("Unsupported transaction type [" + type.name() + "] during fetch from HSQLDB repository"); - case PAYMENT: - return this.paymentTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case REGISTER_NAME: - return this.registerNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case UPDATE_NAME: - return this.updateNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case SELL_NAME: - return this.sellNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CANCEL_SELL_NAME: - return this.cancelSellNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case BUY_NAME: - return this.buyNameTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CREATE_POLL: - return this.createPollTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case VOTE_ON_POLL: - return this.voteOnPollTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case ARBITRARY: - return this.arbitraryTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case ISSUE_ASSET: - return this.issueAssetTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case TRANSFER_ASSET: - return this.transferAssetTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CREATE_ASSET_ORDER: - return this.createOrderTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CANCEL_ASSET_ORDER: - return this.cancelOrderTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case MULTIPAYMENT: - return this.multiPaymentTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case DEPLOY_AT: - return this.deployATTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case MESSAGE: - return this.messageTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case AT: - return this.atTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CREATE_GROUP: - return this.createGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case UPDATE_GROUP: - return this.updateGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case ADD_GROUP_ADMIN: - return this.addGroupAdminTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case REMOVE_GROUP_ADMIN: - return this.removeGroupAdminTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case GROUP_BAN: - return this.groupBanTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CANCEL_GROUP_BAN: - return this.groupUnbanTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case GROUP_KICK: - return this.groupKickTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case GROUP_INVITE: - return this.groupInviteTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case CANCEL_GROUP_INVITE: - return this.cancelGroupInviteTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case JOIN_GROUP: - return this.joinGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - case LEAVE_GROUP: - return this.leaveGroupTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee); - - default: - throw new DataException("Unsupported transaction type [" + type.name() + "] during fetch from HSQLDB repository"); + try { + Method method = txRepository.getClass().getDeclaredMethod("fromBase", byte[].class, byte[].class, byte[].class, long.class, BigDecimal.class); + return (TransactionData) method.invoke(txRepository, signature, reference, creatorPublicKey, timestamp, fee); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new DataException("Unsupported transaction type [" + type.name() + "] during fetch from HSQLDB repository"); } } @@ -490,125 +379,16 @@ public class HSQLDBTransactionRepository implements TransactionRepository { } // Now call transaction-type-specific save() method - switch (transactionData.getType()) { - case GENESIS: - this.genesisTransactionRepository.save(transactionData); - break; + TransactionType type = transactionData.getType(); + HSQLDBTransactionRepository txRepository = repositoryByTxType[type.value]; + if (txRepository == null) + throw new DataException("Unsupported transaction type [" + type.name() + "] during save into HSQLDB repository"); - case PAYMENT: - this.paymentTransactionRepository.save(transactionData); - break; - - case REGISTER_NAME: - this.registerNameTransactionRepository.save(transactionData); - break; - - case UPDATE_NAME: - this.updateNameTransactionRepository.save(transactionData); - break; - - case SELL_NAME: - this.sellNameTransactionRepository.save(transactionData); - break; - - case CANCEL_SELL_NAME: - this.cancelSellNameTransactionRepository.save(transactionData); - break; - - case BUY_NAME: - this.buyNameTransactionRepository.save(transactionData); - break; - - case CREATE_POLL: - this.createPollTransactionRepository.save(transactionData); - break; - - case VOTE_ON_POLL: - this.voteOnPollTransactionRepository.save(transactionData); - break; - - case ARBITRARY: - this.arbitraryTransactionRepository.save(transactionData); - break; - - case ISSUE_ASSET: - this.issueAssetTransactionRepository.save(transactionData); - break; - - case TRANSFER_ASSET: - this.transferAssetTransactionRepository.save(transactionData); - break; - - case CREATE_ASSET_ORDER: - this.createOrderTransactionRepository.save(transactionData); - break; - - case CANCEL_ASSET_ORDER: - this.cancelOrderTransactionRepository.save(transactionData); - break; - - case MULTIPAYMENT: - this.multiPaymentTransactionRepository.save(transactionData); - break; - - case DEPLOY_AT: - this.deployATTransactionRepository.save(transactionData); - break; - - case MESSAGE: - this.messageTransactionRepository.save(transactionData); - break; - - case AT: - this.atTransactionRepository.save(transactionData); - break; - - case CREATE_GROUP: - this.createGroupTransactionRepository.save(transactionData); - break; - - case UPDATE_GROUP: - this.updateGroupTransactionRepository.save(transactionData); - break; - - case ADD_GROUP_ADMIN: - this.addGroupAdminTransactionRepository.save(transactionData); - break; - - case REMOVE_GROUP_ADMIN: - this.removeGroupAdminTransactionRepository.save(transactionData); - break; - - case GROUP_BAN: - this.groupBanTransactionRepository.save(transactionData); - break; - - case CANCEL_GROUP_BAN: - this.groupUnbanTransactionRepository.save(transactionData); - break; - - case GROUP_KICK: - this.groupKickTransactionRepository.save(transactionData); - break; - - case GROUP_INVITE: - this.groupInviteTransactionRepository.save(transactionData); - break; - - case CANCEL_GROUP_INVITE: - this.cancelGroupInviteTransactionRepository.save(transactionData); - break; - - case JOIN_GROUP: - this.joinGroupTransactionRepository.save(transactionData); - break; - - case LEAVE_GROUP: - this.leaveGroupTransactionRepository.save(transactionData); - break; - - default: - throw new DataException("Unsupported transaction type [" + transactionData.getType().name() + "] during save into HSQLDB repository"); + try { + Method method = txRepository.getClass().getDeclaredMethod("save", TransactionData.class); + method.invoke(txRepository, transactionData); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new DataException("Unsupported transaction type [" + type.name() + "] during save into HSQLDB repository"); } } diff --git a/src/main/java/org/qora/transaction/CancelOrderTransaction.java b/src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java similarity index 92% rename from src/main/java/org/qora/transaction/CancelOrderTransaction.java rename to src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java index 847adb3f..b89cebd3 100644 --- a/src/main/java/org/qora/transaction/CancelOrderTransaction.java +++ b/src/main/java/org/qora/transaction/CancelAssetOrderTransaction.java @@ -11,23 +11,23 @@ import org.qora.asset.Asset; import org.qora.asset.Order; import org.qora.crypto.Crypto; import org.qora.data.asset.OrderData; -import org.qora.data.transaction.CancelOrderTransactionData; +import org.qora.data.transaction.CancelAssetOrderTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.repository.AssetRepository; import org.qora.repository.DataException; import org.qora.repository.Repository; -public class CancelOrderTransaction extends Transaction { +public class CancelAssetOrderTransaction extends Transaction { // Properties - private CancelOrderTransactionData cancelOrderTransactionData; + private CancelAssetOrderTransactionData cancelOrderTransactionData; // Constructors - public CancelOrderTransaction(Repository repository, TransactionData transactionData) { + public CancelAssetOrderTransaction(Repository repository, TransactionData transactionData) { super(repository, transactionData); - this.cancelOrderTransactionData = (CancelOrderTransactionData) this.transactionData; + this.cancelOrderTransactionData = (CancelAssetOrderTransactionData) this.transactionData; } // More information diff --git a/src/main/java/org/qora/transaction/CreateOrderTransaction.java b/src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java similarity index 94% rename from src/main/java/org/qora/transaction/CreateOrderTransaction.java rename to src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java index c7843654..619f0321 100644 --- a/src/main/java/org/qora/transaction/CreateOrderTransaction.java +++ b/src/main/java/org/qora/transaction/CreateAssetOrderTransaction.java @@ -12,23 +12,23 @@ import org.qora.asset.Order; import org.qora.block.BlockChain; import org.qora.data.asset.AssetData; import org.qora.data.asset.OrderData; -import org.qora.data.transaction.CreateOrderTransactionData; +import org.qora.data.transaction.CreateAssetOrderTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.repository.AssetRepository; import org.qora.repository.DataException; import org.qora.repository.Repository; -public class CreateOrderTransaction extends Transaction { +public class CreateAssetOrderTransaction extends Transaction { // Properties - private CreateOrderTransactionData createOrderTransactionData; + private CreateAssetOrderTransactionData createOrderTransactionData; // Constructors - public CreateOrderTransaction(Repository repository, TransactionData transactionData) { + public CreateAssetOrderTransaction(Repository repository, TransactionData transactionData) { super(repository, transactionData); - this.createOrderTransactionData = (CreateOrderTransactionData) this.transactionData; + this.createOrderTransactionData = (CreateAssetOrderTransactionData) this.transactionData; } // More information diff --git a/src/main/java/org/qora/transaction/DeployATTransaction.java b/src/main/java/org/qora/transaction/DeployAtTransaction.java similarity index 96% rename from src/main/java/org/qora/transaction/DeployATTransaction.java rename to src/main/java/org/qora/transaction/DeployAtTransaction.java index dca41da2..d420bb9e 100644 --- a/src/main/java/org/qora/transaction/DeployATTransaction.java +++ b/src/main/java/org/qora/transaction/DeployAtTransaction.java @@ -15,7 +15,7 @@ import org.qora.at.AT; import org.qora.block.BlockChain; import org.qora.crypto.Crypto; import org.qora.data.asset.AssetData; -import org.qora.data.transaction.DeployATTransactionData; +import org.qora.data.transaction.DeployAtTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.repository.DataException; import org.qora.repository.Repository; @@ -23,10 +23,10 @@ import org.qora.transform.Transformer; import com.google.common.base.Utf8; -public class DeployATTransaction extends Transaction { +public class DeployAtTransaction extends Transaction { // Properties - private DeployATTransactionData deployATTransactionData; + private DeployAtTransactionData deployATTransactionData; // Other useful constants public static final int MAX_NAME_SIZE = 200; @@ -37,10 +37,10 @@ public class DeployATTransaction extends Transaction { // Constructors - public DeployATTransaction(Repository repository, TransactionData transactionData) { + public DeployAtTransaction(Repository repository, TransactionData transactionData) { super(repository, transactionData); - this.deployATTransactionData = (DeployATTransactionData) this.transactionData; + this.deployATTransactionData = (DeployAtTransactionData) this.transactionData; } // More information diff --git a/src/main/java/org/qora/transaction/Transaction.java b/src/main/java/org/qora/transaction/Transaction.java index 933e4a81..efc23512 100644 --- a/src/main/java/org/qora/transaction/Transaction.java +++ b/src/main/java/org/qora/transaction/Transaction.java @@ -28,6 +28,9 @@ import org.qora.utils.NTP; import static java.util.Arrays.stream; import static java.util.stream.Collectors.toMap; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + public abstract class Transaction { // Transaction types @@ -46,7 +49,7 @@ public abstract class Transaction { TRANSFER_ASSET(12), CREATE_ASSET_ORDER(13), CANCEL_ASSET_ORDER(14), - MULTIPAYMENT(15), + MULTI_PAYMENT(15), DEPLOY_AT(16), MESSAGE(17), DELEGATION(18), @@ -66,11 +69,21 @@ public abstract class Transaction { LEAVE_GROUP(32); public final int value; + public final String valueString; + public final String className; private final static Map map = stream(TransactionType.values()).collect(toMap(type -> type.value, type -> type)); TransactionType(int value) { this.value = value; + this.valueString = String.valueOf(value); + + String[] classNameParts = this.name().toLowerCase().split("_"); + + for (int i = 0; i < classNameParts.length; ++i) + classNameParts[i] = classNameParts[i].substring(0, 1).toUpperCase().concat(classNameParts[i].substring(1)); + + this.className = String.join("", classNameParts); } public static TransactionType valueOf(int value) { @@ -78,6 +91,14 @@ public abstract class Transaction { } } + public static Class getClassByTxType(TransactionType txType) { + try { + return Class.forName(String.join("", Transaction.class.getPackage().getName(), ".", txType.className, "Transaction")); + } catch (ClassNotFoundException e) { + return null; + } + } + // Validation results public enum ValidationResult { OK(1), @@ -183,96 +204,17 @@ public abstract class Transaction { * @return a Transaction subclass, or null if a transaction couldn't be determined/built from passed data */ public static Transaction fromData(Repository repository, TransactionData transactionData) { - switch (transactionData.getType()) { - case GENESIS: - return new GenesisTransaction(repository, transactionData); + TransactionType type = transactionData.getType(); - case PAYMENT: - return new PaymentTransaction(repository, transactionData); + try { + Class transactionClass = Transaction.getClassByTxType(type); + if (transactionClass == null) + throw new IllegalStateException("Unsupported transaction type [" + type.value + "] during fetch from repository"); - case REGISTER_NAME: - return new RegisterNameTransaction(repository, transactionData); - - case UPDATE_NAME: - return new UpdateNameTransaction(repository, transactionData); - - case SELL_NAME: - return new SellNameTransaction(repository, transactionData); - - case CANCEL_SELL_NAME: - return new CancelSellNameTransaction(repository, transactionData); - - case BUY_NAME: - return new BuyNameTransaction(repository, transactionData); - - case CREATE_POLL: - return new CreatePollTransaction(repository, transactionData); - - case VOTE_ON_POLL: - return new VoteOnPollTransaction(repository, transactionData); - - case ARBITRARY: - return new ArbitraryTransaction(repository, transactionData); - - case ISSUE_ASSET: - return new IssueAssetTransaction(repository, transactionData); - - case TRANSFER_ASSET: - return new TransferAssetTransaction(repository, transactionData); - - case CREATE_ASSET_ORDER: - return new CreateOrderTransaction(repository, transactionData); - - case CANCEL_ASSET_ORDER: - return new CancelOrderTransaction(repository, transactionData); - - case MULTIPAYMENT: - return new MultiPaymentTransaction(repository, transactionData); - - case DEPLOY_AT: - return new DeployATTransaction(repository, transactionData); - - case MESSAGE: - return new MessageTransaction(repository, transactionData); - - case AT: - return new ATTransaction(repository, transactionData); - - case CREATE_GROUP: - return new CreateGroupTransaction(repository, transactionData); - - case UPDATE_GROUP: - return new UpdateGroupTransaction(repository, transactionData); - - case ADD_GROUP_ADMIN: - return new AddGroupAdminTransaction(repository, transactionData); - - case REMOVE_GROUP_ADMIN: - return new RemoveGroupAdminTransaction(repository, transactionData); - - case GROUP_BAN: - return new GroupBanTransaction(repository, transactionData); - - case CANCEL_GROUP_BAN: - return new CancelGroupBanTransaction(repository, transactionData); - - case GROUP_KICK: - return new GroupKickTransaction(repository, transactionData); - - case GROUP_INVITE: - return new GroupInviteTransaction(repository, transactionData); - - case CANCEL_GROUP_INVITE: - return new CancelGroupInviteTransaction(repository, transactionData); - - case JOIN_GROUP: - return new JoinGroupTransaction(repository, transactionData); - - case LEAVE_GROUP: - return new LeaveGroupTransaction(repository, transactionData); - - default: - throw new IllegalStateException("Unsupported transaction type [" + transactionData.getType().value + "] during fetch from repository"); + Constructor constructor = transactionClass.getConstructor(Repository.class, TransactionData.class); + return (Transaction) constructor.newInstance(repository, transactionData); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | InstantiationException e) { + throw new IllegalStateException("Internal error with transaction type [" + type.value + "] during fetch from repository"); } } diff --git a/src/main/java/org/qora/transform/block/BlockTransformer.java b/src/main/java/org/qora/transform/block/BlockTransformer.java index d8e3ce73..b1b39685 100644 --- a/src/main/java/org/qora/transform/block/BlockTransformer.java +++ b/src/main/java/org/qora/transform/block/BlockTransformer.java @@ -18,7 +18,7 @@ import org.qora.data.at.ATStateData; import org.qora.data.block.BlockData; import org.qora.data.transaction.TransactionData; import org.qora.repository.DataException; -import org.qora.transaction.CreateOrderTransaction; +import org.qora.transaction.CreateAssetOrderTransaction; import org.qora.transaction.Transaction; import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; @@ -305,7 +305,7 @@ public class BlockTransformer extends Transformer { // If this is an asset CreateOrderTransaction then check to see if any trades happened if (transaction.getTransactionData().getType() == Transaction.TransactionType.CREATE_ASSET_ORDER) { - CreateOrderTransaction orderTransaction = (CreateOrderTransaction) transaction; + CreateAssetOrderTransaction orderTransaction = (CreateAssetOrderTransaction) transaction; Order order = orderTransaction.getOrder(); List trades = order.getTrades(); diff --git a/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java index d0145552..7f07f48d 100644 --- a/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.AddGroupAdminTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -25,6 +26,20 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.ADD_GROUP_ADMIN.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group owner's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("member to promote to admin", TransformationType.ADDRESS); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java index b95f58b5..fb592c8f 100644 --- a/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java @@ -17,6 +17,7 @@ import org.qora.data.transaction.ArbitraryTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.ArbitraryTransactionData.DataType; import org.qora.transaction.ArbitraryTransaction; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.PaymentTransformer; import org.qora.transform.TransformationException; import org.qora.utils.Base58; @@ -37,6 +38,27 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH_V1 = BASE_TYPELESS_LENGTH + SENDER_LENGTH + SERVICE_LENGTH + DATA_SIZE_LENGTH; private static final int TYPELESS_DATALESS_LENGTH_V3 = BASE_TYPELESS_LENGTH + SENDER_LENGTH + PAYMENTS_COUNT_LENGTH + SERVICE_LENGTH + DATA_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.ARBITRARY.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("sender's public key", TransformationType.PUBLIC_KEY); + layout.add("number of payments", TransformationType.INT); + + layout.add("* recipient", TransformationType.ADDRESS); + layout.add("* asset ID of payment", TransformationType.LONG); + layout.add("* payment amount", TransformationType.AMOUNT); + + layout.add("service ID", TransformationType.INT); + layout.add("data length", TransformationType.INT); + layout.add("data", TransformationType.DATA); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java index c8077660..dbbe144a 100644 --- a/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.BuyNameTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.naming.Name; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -28,6 +29,22 @@ public class BuyNameTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + BUYER_LENGTH + NAME_SIZE_LENGTH + AMOUNT_LENGTH + SELLER_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.BUY_NAME.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("buyer's public key", TransformationType.PUBLIC_KEY); + layout.add("name length", TransformationType.INT); + layout.add("name", TransformationType.STRING); + layout.add("buy price", TransformationType.AMOUNT); + layout.add("seller", TransformationType.ADDRESS); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/CancelOrderTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java similarity index 72% rename from src/main/java/org/qora/transform/transaction/CancelOrderTransactionTransformer.java rename to src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java index fbcaa1d2..7845c095 100644 --- a/src/main/java/org/qora/transform/transaction/CancelOrderTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java @@ -7,8 +7,9 @@ import java.nio.ByteBuffer; import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; -import org.qora.data.transaction.CancelOrderTransactionData; +import org.qora.data.transaction.CancelAssetOrderTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Base58; import org.qora.utils.Serialization; @@ -17,7 +18,7 @@ import com.google.common.hash.HashCode; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; -public class CancelOrderTransactionTransformer extends TransactionTransformer { +public class CancelAssetOrderTransactionTransformer extends TransactionTransformer { // Property lengths private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH; @@ -25,6 +26,19 @@ public class CancelOrderTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + ORDER_ID_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CANCEL_ASSET_ORDER.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("order creator's public key", TransformationType.PUBLIC_KEY); + layout.add("order ID to cancel", TransformationType.SIGNATURE); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); @@ -41,7 +55,7 @@ public class CancelOrderTransactionTransformer extends TransactionTransformer { byte[] signature = new byte[SIGNATURE_LENGTH]; byteBuffer.get(signature); - return new CancelOrderTransactionData(creatorPublicKey, orderId, fee, timestamp, reference, signature); + return new CancelAssetOrderTransactionData(creatorPublicKey, orderId, fee, timestamp, reference, signature); } public static int getDataLength(TransactionData transactionData) throws TransformationException { @@ -50,7 +64,7 @@ public class CancelOrderTransactionTransformer extends TransactionTransformer { public static byte[] toBytes(TransactionData transactionData) throws TransformationException { try { - CancelOrderTransactionData cancelOrderTransactionData = (CancelOrderTransactionData) transactionData; + CancelAssetOrderTransactionData cancelOrderTransactionData = (CancelAssetOrderTransactionData) transactionData; ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -77,7 +91,7 @@ public class CancelOrderTransactionTransformer extends TransactionTransformer { JSONObject json = TransactionTransformer.getBaseJSON(transactionData); try { - CancelOrderTransactionData cancelOrderTransactionData = (CancelOrderTransactionData) transactionData; + CancelAssetOrderTransactionData cancelOrderTransactionData = (CancelAssetOrderTransactionData) transactionData; byte[] creatorPublicKey = cancelOrderTransactionData.getCreatorPublicKey(); diff --git a/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java index 673b3493..2a2f3fe2 100644 --- a/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.CancelGroupBanTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -25,6 +26,20 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CANCEL_GROUP_BAN.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group admin's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("account to unban", TransformationType.ADDRESS); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java index 7854e342..c79a2e26 100644 --- a/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.CancelGroupInviteTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -25,6 +26,20 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + INVITEE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CANCEL_GROUP_INVITE.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group admin's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("invitee to no longer invite", TransformationType.ADDRESS); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java index f7218c34..ba27b53c 100644 --- a/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.CancelSellNameTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.naming.Name; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -26,6 +27,20 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CANCEL_SELL_NAME.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("name owner's public key", TransformationType.PUBLIC_KEY); + layout.add("name length", TransformationType.INT); + layout.add("name", TransformationType.STRING); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/CreateOrderTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java similarity index 78% rename from src/main/java/org/qora/transform/transaction/CreateOrderTransactionTransformer.java rename to src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java index e0f8f191..ce989202 100644 --- a/src/main/java/org/qora/transform/transaction/CreateOrderTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java @@ -8,8 +8,9 @@ import java.nio.ByteBuffer; import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.block.BlockChain; -import org.qora.data.transaction.CreateOrderTransactionData; +import org.qora.data.transaction.CreateAssetOrderTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -17,7 +18,7 @@ import com.google.common.hash.HashCode; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; -public class CreateOrderTransactionTransformer extends TransactionTransformer { +public class CreateAssetOrderTransactionTransformer extends TransactionTransformer { // Property lengths private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH; @@ -26,6 +27,22 @@ public class CreateOrderTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + (ASSET_ID_LENGTH + AMOUNT_LENGTH) * 2; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CREATE_ASSET_ORDER.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("order creator's public key", TransformationType.PUBLIC_KEY); + layout.add("ID of asset of offer", TransformationType.LONG); + layout.add("ID of asset wanted", TransformationType.LONG); + layout.add("amount of asset on offer", TransformationType.ASSET_QUANTITY); + layout.add("amount of asset wanted per offered asset", TransformationType.ASSET_QUANTITY); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); @@ -47,7 +64,7 @@ public class CreateOrderTransactionTransformer extends TransactionTransformer { byte[] signature = new byte[SIGNATURE_LENGTH]; byteBuffer.get(signature); - return new CreateOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature); + return new CreateAssetOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature); } public static int getDataLength(TransactionData transactionData) throws TransformationException { @@ -56,7 +73,7 @@ public class CreateOrderTransactionTransformer extends TransactionTransformer { public static byte[] toBytes(TransactionData transactionData) throws TransformationException { try { - CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + CreateAssetOrderTransactionData createOrderTransactionData = (CreateAssetOrderTransactionData) transactionData; ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -94,7 +111,7 @@ public class CreateOrderTransactionTransformer extends TransactionTransformer { // Special v1 version try { - CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + CreateAssetOrderTransactionData createOrderTransactionData = (CreateAssetOrderTransactionData) transactionData; ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -123,7 +140,7 @@ public class CreateOrderTransactionTransformer extends TransactionTransformer { JSONObject json = TransactionTransformer.getBaseJSON(transactionData); try { - CreateOrderTransactionData createOrderTransactionData = (CreateOrderTransactionData) transactionData; + CreateAssetOrderTransactionData createOrderTransactionData = (CreateAssetOrderTransactionData) transactionData; byte[] creatorPublicKey = createOrderTransactionData.getCreatorPublicKey(); diff --git a/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java index 9b133aa4..069260ab 100644 --- a/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.CreateGroupTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.group.Group; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -30,6 +31,23 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + IS_OPEN_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CREATE_GROUP.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group creator's public key", TransformationType.PUBLIC_KEY); + layout.add("group's name length", TransformationType.INT); + layout.add("group's name", TransformationType.STRING); + layout.add("group's description length", TransformationType.INT); + layout.add("group's description", TransformationType.STRING); + layout.add("is group \"open\"?", TransformationType.BOOLEAN); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java index 5429db56..9079188c 100644 --- a/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java @@ -36,6 +36,25 @@ public class CreatePollTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + OPTIONS_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.CREATE_POLL.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("poll creator's public key", TransformationType.PUBLIC_KEY); + layout.add("poll name length", TransformationType.INT); + layout.add("poll name", TransformationType.STRING); + layout.add("poll description length", TransformationType.INT); + layout.add("poll description", TransformationType.STRING); + layout.add("number of options", TransformationType.INT); + layout.add("* poll option length", TransformationType.INT); + layout.add("* poll option", TransformationType.STRING); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/DeployATTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java similarity index 78% rename from src/main/java/org/qora/transform/transaction/DeployATTransactionTransformer.java rename to src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java index 903921f1..f354735c 100644 --- a/src/main/java/org/qora/transform/transaction/DeployATTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java @@ -9,9 +9,10 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.asset.Asset; import org.qora.block.BlockChain; -import org.qora.data.transaction.DeployATTransactionData; +import org.qora.data.transaction.DeployAtTransactionData; import org.qora.data.transaction.TransactionData; -import org.qora.transaction.DeployATTransaction; +import org.qora.transaction.DeployAtTransaction; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -20,7 +21,7 @@ import com.google.common.hash.HashCode; import com.google.common.primitives.Ints; import com.google.common.primitives.Longs; -public class DeployATTransactionTransformer extends TransactionTransformer { +public class DeployAtTransactionTransformer extends TransactionTransformer { // Property lengths private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH; @@ -36,26 +37,48 @@ public class DeployATTransactionTransformer extends TransactionTransformer { + TAGS_SIZE_LENGTH + CREATION_BYTES_SIZE_LENGTH + AMOUNT_LENGTH; private static final int V4_TYPELESS_LENGTH = TYPELESS_LENGTH + ASSET_ID_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.DEPLOY_AT.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("AT creator's public key", TransformationType.PUBLIC_KEY); + layout.add("AT name length", TransformationType.INT); + layout.add("AT name", TransformationType.STRING); + layout.add("AT description length", TransformationType.INT); + layout.add("AT description", TransformationType.STRING); + layout.add("AT tags length", TransformationType.INT); + layout.add("AT tags", TransformationType.STRING); + layout.add("creation bytes length", TransformationType.INT); + layout.add("creation bytes", TransformationType.DATA); + layout.add("AT initial balance", TransformationType.AMOUNT); + layout.add("asset ID used by AT", TransformationType.LONG); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); - int version = DeployATTransaction.getVersionByTimestamp(timestamp); + int version = DeployAtTransaction.getVersionByTimestamp(timestamp); byte[] reference = new byte[REFERENCE_LENGTH]; byteBuffer.get(reference); byte[] creatorPublicKey = Serialization.deserializePublicKey(byteBuffer); - String name = Serialization.deserializeSizedString(byteBuffer, DeployATTransaction.MAX_NAME_SIZE); + String name = Serialization.deserializeSizedString(byteBuffer, DeployAtTransaction.MAX_NAME_SIZE); - String description = Serialization.deserializeSizedString(byteBuffer, DeployATTransaction.MAX_DESCRIPTION_SIZE); + String description = Serialization.deserializeSizedString(byteBuffer, DeployAtTransaction.MAX_DESCRIPTION_SIZE); - String ATType = Serialization.deserializeSizedString(byteBuffer, DeployATTransaction.MAX_AT_TYPE_SIZE); + String ATType = Serialization.deserializeSizedString(byteBuffer, DeployAtTransaction.MAX_AT_TYPE_SIZE); - String tags = Serialization.deserializeSizedString(byteBuffer, DeployATTransaction.MAX_TAGS_SIZE); + String tags = Serialization.deserializeSizedString(byteBuffer, DeployAtTransaction.MAX_TAGS_SIZE); int creationBytesSize = byteBuffer.getInt(); - if (creationBytesSize <= 0 || creationBytesSize > DeployATTransaction.MAX_CREATION_BYTES_SIZE) + if (creationBytesSize <= 0 || creationBytesSize > DeployAtTransaction.MAX_CREATION_BYTES_SIZE) throw new TransformationException("Creation bytes size invalid in DeployAT transaction"); byte[] creationBytes = new byte[creationBytesSize]; @@ -72,16 +95,16 @@ public class DeployATTransactionTransformer extends TransactionTransformer { byte[] signature = new byte[SIGNATURE_LENGTH]; byteBuffer.get(signature); - return new DeployATTransactionData(creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp, reference, + return new DeployAtTransactionData(creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp, reference, signature); } public static int getDataLength(TransactionData transactionData) throws TransformationException { - DeployATTransactionData deployATTransactionData = (DeployATTransactionData) transactionData; + DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData; int dataLength = TYPE_LENGTH; - int version = DeployATTransaction.getVersionByTimestamp(transactionData.getTimestamp()); + int version = DeployAtTransaction.getVersionByTimestamp(transactionData.getTimestamp()); if (version >= 4) dataLength += V4_TYPELESS_LENGTH; @@ -97,9 +120,9 @@ public class DeployATTransactionTransformer extends TransactionTransformer { public static byte[] toBytes(TransactionData transactionData) throws TransformationException { try { - DeployATTransactionData deployATTransactionData = (DeployATTransactionData) transactionData; + DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData; - int version = DeployATTransaction.getVersionByTimestamp(transactionData.getTimestamp()); + int version = DeployAtTransaction.getVersionByTimestamp(transactionData.getTimestamp()); ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -152,7 +175,7 @@ public class DeployATTransactionTransformer extends TransactionTransformer { // Easier to start from scratch try { - DeployATTransactionData deployATTransactionData = (DeployATTransactionData) transactionData; + DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData; ByteArrayOutputStream bytes = new ByteArrayOutputStream(); @@ -189,7 +212,7 @@ public class DeployATTransactionTransformer extends TransactionTransformer { JSONObject json = TransactionTransformer.getBaseJSON(transactionData); try { - DeployATTransactionData deployATTransactionData = (DeployATTransactionData) transactionData; + DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData; byte[] creatorPublicKey = deployATTransactionData.getCreatorPublicKey(); diff --git a/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java index ed8ef8bf..c317341c 100644 --- a/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.asset.Asset; import org.qora.block.BlockChain; import org.qora.data.transaction.GenesisTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -27,6 +28,19 @@ public class GenesisTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH_V1 = TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH; private static final int TYPELESS_LENGTH_V4 = 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("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java index df6098fe..448ee4bb 100644 --- a/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.GroupBanTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.group.Group; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -29,6 +30,23 @@ public class GroupBanTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH + TTL_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.GROUP_BAN.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group admin's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("account to ban", TransformationType.ADDRESS); + layout.add("ban reason length", TransformationType.INT); + layout.add("ban reason", TransformationType.STRING); + layout.add("ban period (seconds) or 0 forever", TransformationType.INT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java index b5d65ccb..b46d2231 100644 --- a/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.GroupInviteTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -26,6 +27,21 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + INVITEE_LENGTH + TTL_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.GROUP_INVITE.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group admin's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("account to invite (invitee)", TransformationType.ADDRESS); + layout.add("invite lifetime (seconds)", TransformationType.INT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java index 0e95442b..a98807f6 100644 --- a/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.GroupKickTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.group.Group; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -28,6 +29,22 @@ public class GroupKickTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.GROUP_KICK.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group admin's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("group member to kick", TransformationType.ADDRESS); + layout.add("kick reason length", TransformationType.INT); + layout.add("kick reason", TransformationType.STRING); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java index 24199d26..65fce444 100644 --- a/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java @@ -12,6 +12,7 @@ import org.qora.block.BlockChain; import org.qora.data.transaction.IssueAssetTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.transaction.IssueAssetTransaction; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -34,6 +35,25 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ISSUER_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH + IS_DIVISIBLE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.ISSUE_ASSET.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("asset issuer's public key", TransformationType.PUBLIC_KEY); + layout.add("asset owner", TransformationType.ADDRESS); + layout.add("asset name length", TransformationType.INT); + layout.add("asset name", TransformationType.STRING); + layout.add("asset description length", TransformationType.INT); + layout.add("asset description", TransformationType.STRING); + layout.add("asset quantity", TransformationType.LONG); + layout.add("can asset quantities be fractional?", TransformationType.BOOLEAN); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java index e565e45a..317d4c2a 100644 --- a/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.JoinGroupTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -24,6 +25,19 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + GROUPID_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.JOIN_GROUP.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("joiner's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java index 05b9a3c1..a46bfb02 100644 --- a/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.LeaveGroupTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -24,6 +25,19 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + GROUPID_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.LEAVE_GROUP.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("leaver's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java index ac4c1705..57ce16dc 100644 --- a/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java @@ -12,6 +12,7 @@ import org.qora.asset.Asset; import org.qora.data.transaction.MessageTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.transaction.MessageTransaction; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -35,6 +36,25 @@ public class MessageTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH_V3 = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + ASSET_ID_LENGTH + AMOUNT_LENGTH + DATA_SIZE_LENGTH + IS_TEXT_LENGTH + IS_ENCRYPTED_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.MESSAGE.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("sender's public key", TransformationType.PUBLIC_KEY); + layout.add("recipient", TransformationType.ADDRESS); + layout.add("asset ID of payment", TransformationType.LONG); + layout.add("payment (can be zero)", TransformationType.AMOUNT); + layout.add("message length", TransformationType.INT); + layout.add("message", TransformationType.DATA); + layout.add("is message encrypted?", TransformationType.BOOLEAN); + layout.add("is message text?", TransformationType.BOOLEAN); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java index b388923b..c5c14747 100644 --- a/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java @@ -15,6 +15,7 @@ import org.qora.block.BlockChain; import org.qora.data.PaymentData; import org.qora.data.transaction.MultiPaymentTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.PaymentTransformer; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -31,6 +32,22 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + PAYMENTS_COUNT_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.MULTI_PAYMENT.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("sender's public key", TransformationType.PUBLIC_KEY); + layout.add("number of payments", TransformationType.INT); + layout.add("* recipient", TransformationType.ADDRESS); + layout.add("* asset ID of payment", TransformationType.LONG); + layout.add("* payment amount", TransformationType.AMOUNT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java index 343430e6..bf7e45fc 100644 --- a/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.PaymentTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -25,6 +26,20 @@ public class PaymentTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.PAYMENT.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("sender's public key", TransformationType.PUBLIC_KEY); + layout.add("recipient", TransformationType.ADDRESS); + layout.add("payment amount", TransformationType.AMOUNT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java index 3e2317b2..6a5bb1b3 100644 --- a/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.RegisterNameTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.naming.Name; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -28,6 +29,23 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + REGISTRANT_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DATA_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.REGISTER_NAME.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("name registrant's public key", TransformationType.PUBLIC_KEY); + layout.add("name owner", TransformationType.ADDRESS); + layout.add("name length", TransformationType.INT); + layout.add("name", TransformationType.STRING); + layout.add("data length", TransformationType.INT); + layout.add("data", TransformationType.STRING); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java index a5cd920c..6adbca0e 100644 --- a/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.RemoveGroupAdminTransactionData; import org.qora.data.transaction.TransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -25,6 +26,20 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.REMOVE_GROUP_ADMIN.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group owner's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("admin to demote", TransformationType.ADDRESS); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java index 7dc75d56..2b402df3 100644 --- a/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.SellNameTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.naming.Name; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -27,6 +28,21 @@ public class SellNameTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + AMOUNT_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.SELL_NAME.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("name owner's public key", TransformationType.PUBLIC_KEY); + layout.add("name length", TransformationType.INT); + layout.add("name", TransformationType.STRING); + layout.add("sale price", TransformationType.AMOUNT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/TransactionTransformer.java b/src/main/java/org/qora/transform/transaction/TransactionTransformer.java index fe5b79ff..326c7f5a 100644 --- a/src/main/java/org/qora/transform/transaction/TransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/TransactionTransformer.java @@ -1,8 +1,17 @@ package org.qora.transform.transaction; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -17,7 +26,7 @@ import org.qora.utils.Base58; import com.google.common.hash.HashCode; -public class TransactionTransformer extends Transformer { +public abstract class TransactionTransformer extends Transformer { private static final Logger LOGGER = LogManager.getLogger(TransactionTransformer.class); @@ -26,6 +35,86 @@ public class TransactionTransformer extends Transformer { protected static final int FEE_LENGTH = BIG_DECIMAL_LENGTH; protected static final int BASE_TYPELESS_LENGTH = TIMESTAMP_LENGTH + REFERENCE_LENGTH + FEE_LENGTH + SIGNATURE_LENGTH; + public enum TransformationType { + TIMESTAMP("milliseconds (long)", TIMESTAMP_LENGTH), + SIGNATURE("transaction signature", SIGNATURE_LENGTH), + PUBLIC_KEY("public key", PUBLIC_KEY_LENGTH), + ADDRESS("address", ADDRESS_LENGTH), + AMOUNT("amount", BIG_DECIMAL_LENGTH), + ASSET_QUANTITY("asset-related quantity", 12), + INT("int", INT_LENGTH), + LONG("long", LONG_LENGTH), + STRING("UTF-8 string of variable length", null), + DATA("opaque data of variable length", null), + BOOLEAN("0 for false, anything else for true", 1); + + public final String description; + public final Integer length; + + TransformationType(String description, Integer length) { + this.description = description; + this.length = length; + } + } + + @XmlAccessorType(XmlAccessType.NONE) + public static class Transformation { + @XmlElement + public String description; + public TransformationType transformation; + + protected Transformation() { + } + + public Transformation(String description, TransformationType format) { + this.description = description; + this.transformation = format; + } + + @XmlElement(name = "format") + public String getFormat() { + return this.transformation.description; + } + + @XmlElement(name = "length") + public Integer getLength() { + return this.transformation.length; + } + } + + public static class TransactionLayout { + private List layout = new ArrayList<>(); + + public void add(String name, TransformationType format) { + layout.add(new Transformation(name, format)); + } + + public List getLayout() { + return this.layout; + } + } + + private static Class getClassByTxType(TransactionType txType) { + try { + return Class.forName(String.join("", TransactionTransformer.class.getPackage().getName(), ".", txType.className, "TransactionTransformer")); + } catch (ClassNotFoundException e) { + return null; + } + } + + public static List getLayoutByTxType(TransactionType txType) { + try { + Class transformerClass = TransactionTransformer.getClassByTxType(txType); + if (transformerClass == null) + return null; + + Field layoutField = transformerClass.getDeclaredField("layout"); + return ((TransactionLayout) layoutField.get(null)).getLayout(); + } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException e) { + return null; + } + } + public static TransactionData fromBytes(byte[] bytes) throws TransformationException { if (bytes == null) return null; @@ -42,278 +131,46 @@ public class TransactionTransformer extends Transformer { return null; try { - switch (type) { - case GENESIS: - return GenesisTransactionTransformer.fromByteBuffer(byteBuffer); + Class transformerClass = TransactionTransformer.getClassByTxType(type); + if (transformerClass == null) + throw new TransformationException("Unsupported transaction type [" + type.value + "] during conversion from bytes"); - case PAYMENT: - return PaymentTransactionTransformer.fromByteBuffer(byteBuffer); - - case REGISTER_NAME: - return RegisterNameTransactionTransformer.fromByteBuffer(byteBuffer); - - case UPDATE_NAME: - return UpdateNameTransactionTransformer.fromByteBuffer(byteBuffer); - - case SELL_NAME: - return SellNameTransactionTransformer.fromByteBuffer(byteBuffer); - - case CANCEL_SELL_NAME: - return CancelSellNameTransactionTransformer.fromByteBuffer(byteBuffer); - - case BUY_NAME: - return BuyNameTransactionTransformer.fromByteBuffer(byteBuffer); - - case CREATE_POLL: - return CreatePollTransactionTransformer.fromByteBuffer(byteBuffer); - - case VOTE_ON_POLL: - return VoteOnPollTransactionTransformer.fromByteBuffer(byteBuffer); - - case ARBITRARY: - return ArbitraryTransactionTransformer.fromByteBuffer(byteBuffer); - - case ISSUE_ASSET: - return IssueAssetTransactionTransformer.fromByteBuffer(byteBuffer); - - case TRANSFER_ASSET: - return TransferAssetTransactionTransformer.fromByteBuffer(byteBuffer); - - case CREATE_ASSET_ORDER: - return CreateOrderTransactionTransformer.fromByteBuffer(byteBuffer); - - case CANCEL_ASSET_ORDER: - return CancelOrderTransactionTransformer.fromByteBuffer(byteBuffer); - - case MULTIPAYMENT: - return MultiPaymentTransactionTransformer.fromByteBuffer(byteBuffer); - - case MESSAGE: - return MessageTransactionTransformer.fromByteBuffer(byteBuffer); - - case DEPLOY_AT: - return DeployATTransactionTransformer.fromByteBuffer(byteBuffer); - - case CREATE_GROUP: - return CreateGroupTransactionTransformer.fromByteBuffer(byteBuffer); - - case UPDATE_GROUP: - return UpdateGroupTransactionTransformer.fromByteBuffer(byteBuffer); - - case ADD_GROUP_ADMIN: - return AddGroupAdminTransactionTransformer.fromByteBuffer(byteBuffer); - - case REMOVE_GROUP_ADMIN: - return RemoveGroupAdminTransactionTransformer.fromByteBuffer(byteBuffer); - - case GROUP_BAN: - return GroupBanTransactionTransformer.fromByteBuffer(byteBuffer); - - case CANCEL_GROUP_BAN: - return CancelGroupBanTransactionTransformer.fromByteBuffer(byteBuffer); - - case GROUP_KICK: - return GroupKickTransactionTransformer.fromByteBuffer(byteBuffer); - - case GROUP_INVITE: - return GroupInviteTransactionTransformer.fromByteBuffer(byteBuffer); - - case CANCEL_GROUP_INVITE: - return CancelGroupInviteTransactionTransformer.fromByteBuffer(byteBuffer); - - case JOIN_GROUP: - return JoinGroupTransactionTransformer.fromByteBuffer(byteBuffer); - - case LEAVE_GROUP: - return LeaveGroupTransactionTransformer.fromByteBuffer(byteBuffer); - - default: - throw new TransformationException("Unsupported transaction type [" + type.value + "] during conversion from bytes"); - } + Method method = transformerClass.getDeclaredMethod("fromByteBuffer", ByteBuffer.class); + return (TransactionData) method.invoke(null, byteBuffer); } catch (BufferUnderflowException e) { throw new TransformationException("Byte data too short for transaction type [" + type.value + "]"); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new TransformationException("Internal error with transaction type [" + type.value + "] during conversion from bytes"); } } public static int getDataLength(TransactionData transactionData) throws TransformationException { - switch (transactionData.getType()) { - case GENESIS: - return GenesisTransactionTransformer.getDataLength(transactionData); + TransactionType type = transactionData.getType(); - case PAYMENT: - return PaymentTransactionTransformer.getDataLength(transactionData); + try { + Class transformerClass = TransactionTransformer.getClassByTxType(type); + if (transformerClass == null) + throw new TransformationException("Unsupported transaction type [" + type.value + "] when requesting byte length"); - case REGISTER_NAME: - return RegisterNameTransactionTransformer.getDataLength(transactionData); - - case UPDATE_NAME: - return UpdateNameTransactionTransformer.getDataLength(transactionData); - - case SELL_NAME: - return SellNameTransactionTransformer.getDataLength(transactionData); - - case CANCEL_SELL_NAME: - return CancelSellNameTransactionTransformer.getDataLength(transactionData); - - case BUY_NAME: - return BuyNameTransactionTransformer.getDataLength(transactionData); - - case CREATE_POLL: - return CreatePollTransactionTransformer.getDataLength(transactionData); - - case VOTE_ON_POLL: - return VoteOnPollTransactionTransformer.getDataLength(transactionData); - - case ARBITRARY: - return ArbitraryTransactionTransformer.getDataLength(transactionData); - - case ISSUE_ASSET: - return IssueAssetTransactionTransformer.getDataLength(transactionData); - - case TRANSFER_ASSET: - return TransferAssetTransactionTransformer.getDataLength(transactionData); - - case CREATE_ASSET_ORDER: - return CreateOrderTransactionTransformer.getDataLength(transactionData); - - case CANCEL_ASSET_ORDER: - return CancelOrderTransactionTransformer.getDataLength(transactionData); - - case MULTIPAYMENT: - return MultiPaymentTransactionTransformer.getDataLength(transactionData); - - case MESSAGE: - return MessageTransactionTransformer.getDataLength(transactionData); - - case DEPLOY_AT: - return DeployATTransactionTransformer.getDataLength(transactionData); - - case CREATE_GROUP: - return CreateGroupTransactionTransformer.getDataLength(transactionData); - - case UPDATE_GROUP: - return UpdateGroupTransactionTransformer.getDataLength(transactionData); - - case ADD_GROUP_ADMIN: - return AddGroupAdminTransactionTransformer.getDataLength(transactionData); - - case REMOVE_GROUP_ADMIN: - return RemoveGroupAdminTransactionTransformer.getDataLength(transactionData); - - case GROUP_BAN: - return GroupBanTransactionTransformer.getDataLength(transactionData); - - case CANCEL_GROUP_BAN: - return CancelGroupBanTransactionTransformer.getDataLength(transactionData); - - case GROUP_KICK: - return GroupKickTransactionTransformer.getDataLength(transactionData); - - case GROUP_INVITE: - return GroupInviteTransactionTransformer.getDataLength(transactionData); - - case CANCEL_GROUP_INVITE: - return CancelGroupInviteTransactionTransformer.getDataLength(transactionData); - - case JOIN_GROUP: - return JoinGroupTransactionTransformer.getDataLength(transactionData); - - case LEAVE_GROUP: - return LeaveGroupTransactionTransformer.getDataLength(transactionData); - - default: - throw new TransformationException("Unsupported transaction type [" + transactionData.getType().value + "] when requesting byte length"); + Method method = transformerClass.getDeclaredMethod("getDataLength", TransactionData.class); + return (int) method.invoke(null, transactionData); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new TransformationException("Internal error with transaction type [" + type.value + "] when requesting byte length"); } } public static byte[] toBytes(TransactionData transactionData) throws TransformationException { - switch (transactionData.getType()) { - case GENESIS: - return GenesisTransactionTransformer.toBytes(transactionData); + TransactionType type = transactionData.getType(); - case PAYMENT: - return PaymentTransactionTransformer.toBytes(transactionData); + try { + Class transformerClass = TransactionTransformer.getClassByTxType(type); + if (transformerClass == null) + throw new TransformationException("Unsupported transaction type [" + type.value + "] during conversion to bytes"); - case REGISTER_NAME: - return RegisterNameTransactionTransformer.toBytes(transactionData); - - case UPDATE_NAME: - return UpdateNameTransactionTransformer.toBytes(transactionData); - - case SELL_NAME: - return SellNameTransactionTransformer.toBytes(transactionData); - - case CANCEL_SELL_NAME: - return CancelSellNameTransactionTransformer.toBytes(transactionData); - - case BUY_NAME: - return BuyNameTransactionTransformer.toBytes(transactionData); - - case CREATE_POLL: - return CreatePollTransactionTransformer.toBytes(transactionData); - - case VOTE_ON_POLL: - return VoteOnPollTransactionTransformer.toBytes(transactionData); - - case ARBITRARY: - return ArbitraryTransactionTransformer.toBytes(transactionData); - - case ISSUE_ASSET: - return IssueAssetTransactionTransformer.toBytes(transactionData); - - case TRANSFER_ASSET: - return TransferAssetTransactionTransformer.toBytes(transactionData); - - case CREATE_ASSET_ORDER: - return CreateOrderTransactionTransformer.toBytes(transactionData); - - case CANCEL_ASSET_ORDER: - return CancelOrderTransactionTransformer.toBytes(transactionData); - - case MULTIPAYMENT: - return MultiPaymentTransactionTransformer.toBytes(transactionData); - - case MESSAGE: - return MessageTransactionTransformer.toBytes(transactionData); - - case DEPLOY_AT: - return DeployATTransactionTransformer.toBytes(transactionData); - - case CREATE_GROUP: - return CreateGroupTransactionTransformer.toBytes(transactionData); - - case UPDATE_GROUP: - return UpdateGroupTransactionTransformer.toBytes(transactionData); - - case ADD_GROUP_ADMIN: - return AddGroupAdminTransactionTransformer.toBytes(transactionData); - - case REMOVE_GROUP_ADMIN: - return RemoveGroupAdminTransactionTransformer.toBytes(transactionData); - - case GROUP_BAN: - return GroupBanTransactionTransformer.toBytes(transactionData); - - case CANCEL_GROUP_BAN: - return CancelGroupBanTransactionTransformer.toBytes(transactionData); - - case GROUP_KICK: - return GroupKickTransactionTransformer.toBytes(transactionData); - - case GROUP_INVITE: - return GroupInviteTransactionTransformer.toBytes(transactionData); - - case CANCEL_GROUP_INVITE: - return CancelGroupInviteTransactionTransformer.toBytes(transactionData); - - case JOIN_GROUP: - return JoinGroupTransactionTransformer.toBytes(transactionData); - - case LEAVE_GROUP: - return LeaveGroupTransactionTransformer.toBytes(transactionData); - - default: - throw new TransformationException("Unsupported transaction type [" + transactionData.getType().value + "] during conversion to bytes"); + Method method = transformerClass.getDeclaredMethod("toBytes", TransactionData.class); + return (byte[]) method.invoke(null, transactionData); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new TransformationException("Internal error with transaction type [" + type.value + "] during conversion to bytes"); } } @@ -327,94 +184,21 @@ public class TransactionTransformer extends Transformer { * @throws TransformationException */ public static byte[] toBytesForSigning(TransactionData transactionData) throws TransformationException { - switch (transactionData.getType()) { - case GENESIS: - return GenesisTransactionTransformer.toBytesForSigningImpl(transactionData); + TransactionType type = transactionData.getType(); - case PAYMENT: - return PaymentTransactionTransformer.toBytesForSigningImpl(transactionData); + try { + Class transformerClass = TransactionTransformer.getClassByTxType(type); + if (transformerClass == null) + throw new TransformationException("Unsupported transaction type [" + type.value + "] during conversion to bytes for signing"); - case REGISTER_NAME: - return RegisterNameTransactionTransformer.toBytesForSigningImpl(transactionData); + // Check method is actually declared in transformer, otherwise we have to call superclass version + if (Arrays.asList(transformerClass.getDeclaredMethods()).stream().noneMatch(method -> method.getName().equals("toBytesForSigningImpl"))) + transformerClass = transformerClass.getSuperclass(); - case UPDATE_NAME: - return UpdateNameTransactionTransformer.toBytesForSigningImpl(transactionData); - - case SELL_NAME: - return SellNameTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CANCEL_SELL_NAME: - return CancelSellNameTransactionTransformer.toBytesForSigningImpl(transactionData); - - case BUY_NAME: - return BuyNameTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CREATE_POLL: - return CreatePollTransactionTransformer.toBytesForSigningImpl(transactionData); - - case VOTE_ON_POLL: - return VoteOnPollTransactionTransformer.toBytesForSigningImpl(transactionData); - - case ARBITRARY: - return ArbitraryTransactionTransformer.toBytesForSigningImpl(transactionData); - - case ISSUE_ASSET: - return IssueAssetTransactionTransformer.toBytesForSigningImpl(transactionData); - - case TRANSFER_ASSET: - return TransferAssetTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CREATE_ASSET_ORDER: - return CreateOrderTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CANCEL_ASSET_ORDER: - return CancelOrderTransactionTransformer.toBytesForSigningImpl(transactionData); - - case MULTIPAYMENT: - return MultiPaymentTransactionTransformer.toBytesForSigningImpl(transactionData); - - case MESSAGE: - return MessageTransactionTransformer.toBytesForSigningImpl(transactionData); - - case DEPLOY_AT: - return DeployATTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CREATE_GROUP: - return CreateGroupTransactionTransformer.toBytesForSigningImpl(transactionData); - - case UPDATE_GROUP: - return UpdateGroupTransactionTransformer.toBytesForSigningImpl(transactionData); - - case ADD_GROUP_ADMIN: - return AddGroupAdminTransactionTransformer.toBytesForSigningImpl(transactionData); - - case REMOVE_GROUP_ADMIN: - return RemoveGroupAdminTransactionTransformer.toBytesForSigningImpl(transactionData); - - case GROUP_BAN: - return GroupBanTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CANCEL_GROUP_BAN: - return CancelGroupBanTransactionTransformer.toBytesForSigningImpl(transactionData); - - case GROUP_KICK: - return GroupKickTransactionTransformer.toBytesForSigningImpl(transactionData); - - case GROUP_INVITE: - return GroupInviteTransactionTransformer.toBytesForSigningImpl(transactionData); - - case CANCEL_GROUP_INVITE: - return CancelGroupInviteTransactionTransformer.toBytesForSigningImpl(transactionData); - - case JOIN_GROUP: - return JoinGroupTransactionTransformer.toBytesForSigningImpl(transactionData); - - case LEAVE_GROUP: - return LeaveGroupTransactionTransformer.toBytesForSigningImpl(transactionData); - - default: - throw new TransformationException( - "Unsupported transaction type [" + transactionData.getType().value + "] during conversion to bytes for signing"); + Method method = transformerClass.getDeclaredMethod("toBytesForSigningImpl", TransactionData.class); + return (byte[]) method.invoke(null, transactionData); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new TransformationException("Internal error with transaction type [" + type.value + "] during conversion to bytes for signing"); } } @@ -439,93 +223,17 @@ public class TransactionTransformer extends Transformer { } public static JSONObject toJSON(TransactionData transactionData) throws TransformationException { - switch (transactionData.getType()) { - case GENESIS: - return GenesisTransactionTransformer.toJSON(transactionData); + TransactionType type = transactionData.getType(); - case PAYMENT: - return PaymentTransactionTransformer.toJSON(transactionData); + try { + Class transformerClass = TransactionTransformer.getClassByTxType(type); + if (transformerClass == null) + throw new TransformationException("Unsupported transaction type [" + type.value + "] during conversion to JSON"); - case REGISTER_NAME: - return RegisterNameTransactionTransformer.toJSON(transactionData); - - case UPDATE_NAME: - return UpdateNameTransactionTransformer.toJSON(transactionData); - - case SELL_NAME: - return SellNameTransactionTransformer.toJSON(transactionData); - - case CANCEL_SELL_NAME: - return CancelSellNameTransactionTransformer.toJSON(transactionData); - - case BUY_NAME: - return BuyNameTransactionTransformer.toJSON(transactionData); - - case CREATE_POLL: - return CreatePollTransactionTransformer.toJSON(transactionData); - - case VOTE_ON_POLL: - return VoteOnPollTransactionTransformer.toJSON(transactionData); - - case ARBITRARY: - return ArbitraryTransactionTransformer.toJSON(transactionData); - - case ISSUE_ASSET: - return IssueAssetTransactionTransformer.toJSON(transactionData); - - case TRANSFER_ASSET: - return TransferAssetTransactionTransformer.toJSON(transactionData); - - case CREATE_ASSET_ORDER: - return CreateOrderTransactionTransformer.toJSON(transactionData); - - case CANCEL_ASSET_ORDER: - return CancelOrderTransactionTransformer.toJSON(transactionData); - - case MULTIPAYMENT: - return MultiPaymentTransactionTransformer.toJSON(transactionData); - - case MESSAGE: - return MessageTransactionTransformer.toJSON(transactionData); - - case DEPLOY_AT: - return DeployATTransactionTransformer.toJSON(transactionData); - - case CREATE_GROUP: - return CreateGroupTransactionTransformer.toJSON(transactionData); - - case UPDATE_GROUP: - return UpdateGroupTransactionTransformer.toJSON(transactionData); - - case ADD_GROUP_ADMIN: - return AddGroupAdminTransactionTransformer.toJSON(transactionData); - - case REMOVE_GROUP_ADMIN: - return RemoveGroupAdminTransactionTransformer.toJSON(transactionData); - - case GROUP_BAN: - return GroupBanTransactionTransformer.toJSON(transactionData); - - case CANCEL_GROUP_BAN: - return CancelGroupBanTransactionTransformer.toJSON(transactionData); - - case GROUP_KICK: - return GroupKickTransactionTransformer.toJSON(transactionData); - - case GROUP_INVITE: - return GroupInviteTransactionTransformer.toJSON(transactionData); - - case CANCEL_GROUP_INVITE: - return CancelGroupInviteTransactionTransformer.toJSON(transactionData); - - case JOIN_GROUP: - return JoinGroupTransactionTransformer.toJSON(transactionData); - - case LEAVE_GROUP: - return LeaveGroupTransactionTransformer.toJSON(transactionData); - - default: - throw new TransformationException("Unsupported transaction type [" + transactionData.getType().value + "] during conversion to JSON"); + Method method = transformerClass.getDeclaredMethod("toJSON", TransactionData.class); + return (JSONObject) method.invoke(null, transactionData); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new TransformationException("Internal error with transaction type [" + type.value + "] during conversion to JSON"); } } diff --git a/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java index 707edd0e..5d89d8eb 100644 --- a/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.TransferAssetTransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -26,6 +27,20 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + ASSET_ID_LENGTH + AMOUNT_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.TRANSFER_ASSET.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("asset owner's public key", TransformationType.PUBLIC_KEY); + layout.add("asset's new owner", TransformationType.ADDRESS); + layout.add("asset ID", TransformationType.LONG); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java index fa1f80ae..abda115e 100644 --- a/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.UpdateGroupTransactionData; import org.qora.data.transaction.TransactionData; import org.qora.group.Group; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -30,6 +31,23 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + NEW_OWNER_LENGTH + NEW_DESCRIPTION_SIZE_LENGTH + NEW_IS_OPEN_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.UPDATE_GROUP.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("group owner's public key", TransformationType.PUBLIC_KEY); + layout.add("group ID", TransformationType.INT); + layout.add("group's new owner", TransformationType.ADDRESS); + layout.add("group's new description length", TransformationType.INT); + layout.add("group's new description", TransformationType.STRING); + layout.add("is group \"open\"?", TransformationType.BOOLEAN); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java index 32de4eb6..0bc47b8d 100644 --- a/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java @@ -10,6 +10,7 @@ import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.UpdateNameTransactionData; import org.qora.naming.Name; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; @@ -28,6 +29,23 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + REGISTRANT_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DATA_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.UPDATE_NAME.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("name owner's public key", TransformationType.PUBLIC_KEY); + layout.add("name's new owner", TransformationType.ADDRESS); + layout.add("name length", TransformationType.INT); + layout.add("name", TransformationType.STRING); + layout.add("new data length", TransformationType.INT); + layout.add("new data", TransformationType.STRING); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java index 92218001..82e72151 100644 --- a/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java +++ b/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java @@ -9,6 +9,7 @@ import org.json.simple.JSONObject; import org.qora.account.PublicKeyAccount; import org.qora.data.transaction.TransactionData; import org.qora.data.transaction.VoteOnPollTransactionData; +import org.qora.transaction.Transaction.TransactionType; import org.qora.transform.TransformationException; import org.qora.utils.Serialization; import org.qora.voting.Poll; @@ -26,6 +27,21 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer { private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + VOTER_LENGTH + NAME_SIZE_LENGTH; + protected static final TransactionLayout layout; + + static { + layout = new TransactionLayout(); + layout.add("txType: " + TransactionType.VOTE_ON_POLL.valueString, TransformationType.INT); + layout.add("timestamp", TransformationType.TIMESTAMP); + layout.add("reference", TransformationType.SIGNATURE); + layout.add("voter's public key", TransformationType.PUBLIC_KEY); + layout.add("poll name length", TransformationType.INT); + layout.add("poll name", TransformationType.STRING); + layout.add("poll option index (0+)", TransformationType.INT); + layout.add("fee", TransformationType.AMOUNT); + layout.add("signature", TransformationType.SIGNATURE); + } + static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException { long timestamp = byteBuffer.getLong(); diff --git a/src/test/java/org/qora/test/ATTests.java b/src/test/java/org/qora/test/ATTests.java index 099de1e7..7fa6ce63 100644 --- a/src/test/java/org/qora/test/ATTests.java +++ b/src/test/java/org/qora/test/ATTests.java @@ -5,11 +5,11 @@ import org.qora.asset.Asset; import org.qora.data.at.ATStateData; import org.qora.data.block.BlockData; import org.qora.data.block.BlockTransactionData; -import org.qora.data.transaction.DeployATTransactionData; +import org.qora.data.transaction.DeployAtTransactionData; import org.qora.repository.DataException; import org.qora.repository.Repository; import org.qora.repository.RepositoryManager; -import org.qora.transaction.DeployATTransaction; +import org.qora.transaction.DeployAtTransaction; import org.qora.transform.TransformationException; import org.qora.utils.Base58; @@ -46,13 +46,13 @@ public class ATTests extends Common { byte[] reference = Base58.decode("2D3jX1pEgu6irsQ7QzJb85QP1D9M45dNyP5M9a3WFHndU5ZywF4F5pnUurcbzMnGMcTwpAY6H7DuLw8cUBU66ao1"); byte[] signature = Base58.decode("2dZ4megUyNoYYY7qWmuSd4xw1yUKgPPF97yBbeddh8aKuC8PLpz7Xvf3r6Zjv1zwGrR8fEAHuaztCPD4KQp76KdL"); - DeployATTransactionData transactionData = new DeployATTransactionData(creatorPublicKey, name, description, ATType, tags, creationBytes, amount, + DeployAtTransactionData transactionData = new DeployAtTransactionData(creatorPublicKey, name, description, ATType, tags, creationBytes, amount, Asset.QORA, fee, timestamp, reference, signature); try (final Repository repository = RepositoryManager.getRepository()) { repository.getTransactionRepository().save(transactionData); - DeployATTransaction transaction = new DeployATTransaction(repository, transactionData); + DeployAtTransaction transaction = new DeployAtTransaction(repository, transactionData); // Fake entry for this transaction at block height 125598 if it doesn't already exist if (transaction.getHeight() == 0) { diff --git a/src/test/java/org/qora/test/CompatibilityTests.java b/src/test/java/org/qora/test/CompatibilityTests.java index 0a70991e..49737dbf 100644 --- a/src/test/java/org/qora/test/CompatibilityTests.java +++ b/src/test/java/org/qora/test/CompatibilityTests.java @@ -2,7 +2,7 @@ package org.qora.test; import org.junit.jupiter.api.Test; import org.qora.data.transaction.TransactionData; -import org.qora.transaction.CreateOrderTransaction; +import org.qora.transaction.CreateAssetOrderTransaction; import org.qora.transaction.CreatePollTransaction; import org.qora.transaction.IssueAssetTransaction; import org.qora.transform.TransformationException; @@ -27,7 +27,7 @@ public class CompatibilityTests { TransactionData transactionData = TransactionTransformer.fromBytes(rawTx); - CreateOrderTransaction transaction = new CreateOrderTransaction(null, transactionData); + CreateAssetOrderTransaction transaction = new CreateAssetOrderTransaction(null, transactionData); assertTrue(transaction.isSignatureValid()); } diff --git a/src/test/java/org/qora/test/SerializationTests.java b/src/test/java/org/qora/test/SerializationTests.java index 222ee581..7837af8e 100644 --- a/src/test/java/org/qora/test/SerializationTests.java +++ b/src/test/java/org/qora/test/SerializationTests.java @@ -143,7 +143,7 @@ public class SerializationTests extends Common { @Test public void testMultiPaymentSerialization() throws TransformationException, DataException { - testSpecificBlockTransactions(34500, TransactionType.MULTIPAYMENT); + testSpecificBlockTransactions(34500, TransactionType.MULTI_PAYMENT); } @Test diff --git a/src/test/java/org/qora/test/TransactionTests.java b/src/test/java/org/qora/test/TransactionTests.java index ac87e530..2b60fb01 100644 --- a/src/test/java/org/qora/test/TransactionTests.java +++ b/src/test/java/org/qora/test/TransactionTests.java @@ -16,9 +16,9 @@ import org.qora.data.asset.TradeData; import org.qora.data.block.BlockData; import org.qora.data.naming.NameData; import org.qora.data.transaction.BuyNameTransactionData; -import org.qora.data.transaction.CancelOrderTransactionData; +import org.qora.data.transaction.CancelAssetOrderTransactionData; import org.qora.data.transaction.CancelSellNameTransactionData; -import org.qora.data.transaction.CreateOrderTransactionData; +import org.qora.data.transaction.CreateAssetOrderTransactionData; import org.qora.data.transaction.CreatePollTransactionData; import org.qora.data.transaction.IssueAssetTransactionData; import org.qora.data.transaction.MessageTransactionData; @@ -41,9 +41,9 @@ import org.qora.repository.RepositoryManager; import org.qora.repository.hsqldb.HSQLDBRepositoryFactory; import org.qora.settings.Settings; import org.qora.transaction.BuyNameTransaction; -import org.qora.transaction.CancelOrderTransaction; +import org.qora.transaction.CancelAssetOrderTransaction; import org.qora.transaction.CancelSellNameTransaction; -import org.qora.transaction.CreateOrderTransaction; +import org.qora.transaction.CreateAssetOrderTransaction; import org.qora.transaction.CreatePollTransaction; import org.qora.transaction.IssueAssetTransaction; import org.qora.transaction.MessageTransaction; @@ -816,9 +816,9 @@ public class TransactionTests { BigDecimal fee = BigDecimal.ONE; long timestamp = parentBlockData.getTimestamp() + 1_000; - CreateOrderTransactionData createOrderTransactionData = new CreateOrderTransactionData(buyer.getPublicKey(), haveAssetId, wantAssetId, amount, price, + CreateAssetOrderTransactionData createOrderTransactionData = new CreateAssetOrderTransactionData(buyer.getPublicKey(), haveAssetId, wantAssetId, amount, price, fee, timestamp, buyersReference); - Transaction createOrderTransaction = new CreateOrderTransaction(this.repository, createOrderTransactionData); + Transaction createOrderTransaction = new CreateAssetOrderTransaction(this.repository, createOrderTransactionData); createOrderTransaction.sign(buyer); assertTrue(createOrderTransaction.isSignatureValid()); assertEquals(ValidationResult.OK, createOrderTransaction.isValid()); @@ -897,9 +897,9 @@ public class TransactionTests { BigDecimal fee = BigDecimal.ONE; long timestamp = parentBlockData.getTimestamp() + 1_000; byte[] buyersReference = buyer.getLastReference(); - CancelOrderTransactionData cancelOrderTransactionData = new CancelOrderTransactionData(buyer.getPublicKey(), orderId, fee, timestamp, buyersReference); + CancelAssetOrderTransactionData cancelOrderTransactionData = new CancelAssetOrderTransactionData(buyer.getPublicKey(), orderId, fee, timestamp, buyersReference); - Transaction cancelOrderTransaction = new CancelOrderTransaction(this.repository, cancelOrderTransactionData); + Transaction cancelOrderTransaction = new CancelAssetOrderTransaction(this.repository, cancelOrderTransactionData); cancelOrderTransaction.sign(buyer); assertTrue(cancelOrderTransaction.isSignatureValid()); assertEquals(ValidationResult.OK, cancelOrderTransaction.isValid()); @@ -972,9 +972,9 @@ public class TransactionTests { long timestamp = parentBlockData.getTimestamp() + 1_000; BigDecimal senderPreTradeWantBalance = sender.getConfirmedBalance(wantAssetId); - CreateOrderTransactionData createOrderTransactionData = new CreateOrderTransactionData(sender.getPublicKey(), haveAssetId, wantAssetId, amount, price, + CreateAssetOrderTransactionData createOrderTransactionData = new CreateAssetOrderTransactionData(sender.getPublicKey(), haveAssetId, wantAssetId, amount, price, fee, timestamp, reference); - Transaction createOrderTransaction = new CreateOrderTransaction(this.repository, createOrderTransactionData); + Transaction createOrderTransaction = new CreateAssetOrderTransaction(this.repository, createOrderTransactionData); createOrderTransaction.sign(sender); assertTrue(createOrderTransaction.isSignatureValid()); assertEquals(ValidationResult.OK, createOrderTransaction.isValid());