diff --git a/log4j2.properties b/log4j2.properties
index 3188c2ff..ccb88f61 100644
--- a/log4j2.properties
+++ b/log4j2.properties
@@ -18,23 +18,18 @@ logger.hsqldbDebug.level = debug
logger.jerseyInject.name = org.glassfish.jersey.internal.inject.Providers
logger.jerseyInject.level = error
-# Debugging transaction searches
-logger.txSearch.name = org.qora.repository.hsqldb.transaction.HSQLDBTransactionRepository
-logger.txSearch.level = trace
+# Suppress extraneous Jetty entries
+# 2019-02-14 11:46:27 INFO ContextHandler:851 - Started o.e.j.s.ServletContextHandler@6949e948{/,null,AVAILABLE}
+# 2019-02-14 11:46:27 INFO AbstractConnector:289 - Started ServerConnector@50ad322b{HTTP/1.1,[http/1.1]}{0.0.0.0:9085}
+# 2019-02-14 11:46:27 INFO Server:374 - jetty-9.4.11.v20180605; built: 2018-06-05T18:24:03.829Z; git: d5fc0523cfa96bfebfbda19606cad384d772f04c; jvm 1.8.0_181-b13
+# 2019-02-14 11:46:27 INFO Server:411 - Started @2539ms
+logger.oejsSCH.name = org.eclipse.jetty
+logger.oejsSCH.level = warn
-# Debug block generator
-logger.blockgen.name = org.qora.block.BlockGenerator
-logger.blockgen.level = trace
-
-# Debug synchronization
-logger.sync.name = org.qora.controller.Synchronizer
-logger.sync.level = trace
-
-# Debug networking
-logger.network.name = org.qora.network.Network
-logger.network.level = trace
-logger.peer.name = org.qora.network.Peer
-logger.peer.level = trace
+# Suppress extraneous slf4j entries
+# 2019-02-14 11:46:27 INFO log:193 - Logging initialized @1636ms to org.eclipse.jetty.util.log.Slf4jLog
+logger.slf4j.name = org.slf4j
+logger.slf4j.level = warn
appender.console.type = Console
appender.console.name = stdout
diff --git a/src/main/java/org/qora/account/Account.java b/src/main/java/org/qora/account/Account.java
index 05d415eb..8a153321 100644
--- a/src/main/java/org/qora/account/Account.java
+++ b/src/main/java/org/qora/account/Account.java
@@ -24,7 +24,7 @@ public class Account {
public static final int ADDRESS_LENGTH = 25;
protected Repository repository;
- protected AccountData accountData;
+ protected String address;
protected Account() {
}
@@ -32,11 +32,24 @@ public class Account {
/** Construct Account business object using account's address */
public Account(Repository repository, String address) {
this.repository = repository;
- this.accountData = new AccountData(address);
+ this.address = address;
}
+ // Simple getters / setters
+
public String getAddress() {
- return this.accountData.getAddress();
+ return this.address;
+ }
+
+ /**
+ * Build AccountData object using available account information.
+ *
+ * For example, PublicKeyAccount might override and add public key info.
+ *
+ * @return
+ */
+ protected AccountData buildAccountData() {
+ return new AccountData(this.address);
}
// More information
@@ -109,7 +122,7 @@ public class Account {
}
public BigDecimal getConfirmedBalance(long assetId) throws DataException {
- AccountBalanceData accountBalanceData = this.repository.getAccountRepository().getBalance(this.accountData.getAddress(), assetId);
+ AccountBalanceData accountBalanceData = this.repository.getAccountRepository().getBalance(this.address, assetId);
if (accountBalanceData == null)
return BigDecimal.ZERO.setScale(8);
@@ -118,16 +131,16 @@ public class Account {
public void setConfirmedBalance(long assetId, BigDecimal balance) throws DataException {
// Can't have a balance without an account - make sure it exists!
- this.repository.getAccountRepository().create(this.accountData);
+ this.repository.getAccountRepository().ensureAccount(this.buildAccountData());
- AccountBalanceData accountBalanceData = new AccountBalanceData(this.accountData.getAddress(), assetId, balance);
+ AccountBalanceData accountBalanceData = new AccountBalanceData(this.address, assetId, balance);
this.repository.getAccountRepository().save(accountBalanceData);
- LOGGER.trace(this.accountData.getAddress() + " balance now: " + balance.toPlainString() + " [assetId " + assetId + "]");
+ LOGGER.trace(this.address + " balance now: " + balance.toPlainString() + " [assetId " + assetId + "]");
}
public void deleteBalance(long assetId) throws DataException {
- this.repository.getAccountRepository().delete(this.accountData.getAddress(), assetId);
+ this.repository.getAccountRepository().delete(this.address, assetId);
}
// Reference manipulations
@@ -139,17 +152,13 @@ public class Account {
* @throws DataException
*/
public byte[] getLastReference() throws DataException {
- AccountData accountData = this.repository.getAccountRepository().getAccount(this.accountData.getAddress());
- if (accountData == null)
- return null;
-
- return accountData.getReference();
+ return this.repository.getAccountRepository().getLastReference(this.address);
}
/**
* Fetch last reference for account, considering unconfirmed transactions.
*
- * NOTE: repository.discardChanges() may be called during execution.
+ * NOTE: a repository savepoint may be used during execution.
*
* @return byte[] reference, or null if no reference or account not found.
* @throws DataException
@@ -163,7 +172,7 @@ public class Account {
for (TransactionData transactionData : unconfirmedTransactions) {
String address = PublicKeyAccount.getAddress(transactionData.getCreatorPublicKey());
- if (address.equals(this.accountData.getAddress()))
+ if (address.equals(this.address))
reference = transactionData.getSignature();
}
@@ -182,9 +191,30 @@ public class Account {
* @throws DataException
*/
public void setLastReference(byte[] reference) throws DataException {
+ AccountData accountData = this.buildAccountData();
accountData.setReference(reference);
+ this.repository.getAccountRepository().setLastReference(accountData);
+ }
- this.repository.getAccountRepository().save(accountData);
+ // Default groupID manipulations
+
+ /** Returns account's default groupID or null if account doesn't exist. */
+ public Integer getDefaultGroupId() throws DataException {
+ return this.repository.getAccountRepository().getDefaultGroupId(this.address);
+ }
+
+ /**
+ * Sets account's default groupID and saves into repository.
+ *
+ * Caller will need to call repository.saveChanges().
+ *
+ * @param defaultGroupId
+ * @throws DataException
+ */
+ public void setDefaultGroupId(int defaultGroupId) throws DataException {
+ AccountData accountData = this.buildAccountData();
+ accountData.setDefaultGroupId(defaultGroupId);
+ this.repository.getAccountRepository().setDefaultGroupId(accountData);
}
}
diff --git a/src/main/java/org/qora/account/PrivateKeyAccount.java b/src/main/java/org/qora/account/PrivateKeyAccount.java
index ce896b8c..2d178faf 100644
--- a/src/main/java/org/qora/account/PrivateKeyAccount.java
+++ b/src/main/java/org/qora/account/PrivateKeyAccount.java
@@ -2,7 +2,6 @@ package org.qora.account;
import org.qora.crypto.Crypto;
import org.qora.crypto.Ed25519;
-import org.qora.data.account.AccountData;
import org.qora.repository.Repository;
import org.qora.utils.Pair;
@@ -16,15 +15,16 @@ public class PrivateKeyAccount extends PublicKeyAccount {
*
* @param seed
* byte[32] used to create private/public key pair
- * @throws IllegalArgumentException if passed invalid seed
+ * @throws IllegalArgumentException
+ * if passed invalid seed
*/
public PrivateKeyAccount(Repository repository, byte[] seed) {
this.repository = repository;
this.seed = seed;
this.keyPair = Ed25519.createKeyPair(seed);
- byte[] publicKey = keyPair.getB();
- this.accountData = new AccountData(Crypto.toAddress(publicKey), null, publicKey);
+ this.publicKey = keyPair.getB();
+ this.address = Crypto.toAddress(publicKey);
}
public byte[] getSeed() {
diff --git a/src/main/java/org/qora/account/PublicKeyAccount.java b/src/main/java/org/qora/account/PublicKeyAccount.java
index ae9af10b..fac8dd96 100644
--- a/src/main/java/org/qora/account/PublicKeyAccount.java
+++ b/src/main/java/org/qora/account/PublicKeyAccount.java
@@ -2,25 +2,35 @@ package org.qora.account;
import org.qora.crypto.Crypto;
import org.qora.crypto.Ed25519;
+import org.qora.data.account.AccountData;
import org.qora.repository.Repository;
public class PublicKeyAccount extends Account {
+ protected byte[] publicKey;
+
public PublicKeyAccount(Repository repository, byte[] publicKey) {
super(repository, Crypto.toAddress(publicKey));
- this.accountData.setPublicKey(publicKey);
+ this.publicKey = publicKey;
}
protected PublicKeyAccount() {
}
public byte[] getPublicKey() {
- return this.accountData.getPublicKey();
+ return this.publicKey;
+ }
+
+ @Override
+ protected AccountData buildAccountData() {
+ AccountData accountData = super.buildAccountData();
+ accountData.setPublicKey(this.publicKey);
+ return accountData;
}
public boolean verify(byte[] signature, byte[] message) {
- return PublicKeyAccount.verify(this.accountData.getPublicKey(), signature, message);
+ return PublicKeyAccount.verify(this.publicKey, signature, message);
}
public static boolean verify(byte[] publicKey, byte[] signature, byte[] message) {
diff --git a/src/main/java/org/qora/api/resource/AddressesResource.java b/src/main/java/org/qora/api/resource/AddressesResource.java
index 041ef063..f3bacb6d 100644
--- a/src/main/java/org/qora/api/resource/AddressesResource.java
+++ b/src/main/java/org/qora/api/resource/AddressesResource.java
@@ -38,6 +38,31 @@ public class AddressesResource {
@Context
HttpServletRequest request;
+ @GET
+ @Path("/{address}")
+ @Operation(
+ summary = "Return general account information for the given address",
+ responses = {
+ @ApiResponse(
+ description = "general account information",
+ content = @Content(mediaType = MediaType.APPLICATION_JSON, schema = @Schema(implementation = AccountData.class))
+ )
+ }
+ )
+ @ApiErrors({ApiError.INVALID_ADDRESS, ApiError.REPOSITORY_ISSUE})
+ public AccountData getAccountInfo(@PathParam("address") String address) {
+ if (!Crypto.isValidAddress(address))
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.INVALID_ADDRESS);
+
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ return repository.getAccountRepository().getAccount(address);
+ } catch (ApiException e) {
+ throw e;
+ } catch (DataException e) {
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+ }
+ }
+
@GET
@Path("/lastreference/{address}")
@Operation(
diff --git a/src/main/java/org/qora/api/resource/GroupsResource.java b/src/main/java/org/qora/api/resource/GroupsResource.java
index 66d2e7cf..da68de54 100644
--- a/src/main/java/org/qora/api/resource/GroupsResource.java
+++ b/src/main/java/org/qora/api/resource/GroupsResource.java
@@ -38,6 +38,7 @@ import org.qora.data.group.GroupMemberData;
import org.qora.data.transaction.AddGroupAdminTransactionData;
import org.qora.data.transaction.CancelGroupInviteTransactionData;
import org.qora.data.transaction.CreateGroupTransactionData;
+import org.qora.data.transaction.GroupApprovalTransactionData;
import org.qora.data.transaction.GroupBanTransactionData;
import org.qora.data.transaction.GroupInviteTransactionData;
import org.qora.data.transaction.GroupKickTransactionData;
@@ -45,6 +46,7 @@ import org.qora.data.transaction.CancelGroupBanTransactionData;
import org.qora.data.transaction.JoinGroupTransactionData;
import org.qora.data.transaction.LeaveGroupTransactionData;
import org.qora.data.transaction.RemoveGroupAdminTransactionData;
+import org.qora.data.transaction.SetGroupTransactionData;
import org.qora.data.transaction.UpdateGroupTransactionData;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
@@ -55,6 +57,7 @@ import org.qora.transform.TransformationException;
import org.qora.transform.transaction.AddGroupAdminTransactionTransformer;
import org.qora.transform.transaction.CancelGroupInviteTransactionTransformer;
import org.qora.transform.transaction.CreateGroupTransactionTransformer;
+import org.qora.transform.transaction.GroupApprovalTransactionTransformer;
import org.qora.transform.transaction.GroupBanTransactionTransformer;
import org.qora.transform.transaction.GroupInviteTransactionTransformer;
import org.qora.transform.transaction.GroupKickTransactionTransformer;
@@ -62,6 +65,7 @@ import org.qora.transform.transaction.CancelGroupBanTransactionTransformer;
import org.qora.transform.transaction.JoinGroupTransactionTransformer;
import org.qora.transform.transaction.LeaveGroupTransactionTransformer;
import org.qora.transform.transaction.RemoveGroupAdminTransactionTransformer;
+import org.qora.transform.transaction.SetGroupTransactionTransformer;
import org.qora.transform.transaction.UpdateGroupTransactionTransformer;
import org.qora.utils.Base58;
@@ -800,4 +804,90 @@ public class GroupsResource {
}
}
+ @POST
+ @Path("/approval")
+ @Operation(
+ summary = "Build raw, unsigned, GROUP_APPROVAL transaction",
+ requestBody = @RequestBody(
+ required = true,
+ content = @Content(
+ mediaType = MediaType.APPLICATION_JSON,
+ schema = @Schema(
+ implementation = GroupApprovalTransactionData.class
+ )
+ )
+ ),
+ responses = {
+ @ApiResponse(
+ description = "raw, unsigned, GROUP_APPROVAL transaction encoded in Base58",
+ content = @Content(
+ mediaType = MediaType.TEXT_PLAIN,
+ schema = @Schema(
+ type = "string"
+ )
+ )
+ )
+ }
+ )
+ @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
+ public String groupApproval(GroupApprovalTransactionData transactionData) {
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ Transaction transaction = Transaction.fromData(repository, transactionData);
+
+ ValidationResult result = transaction.isValidUnconfirmed();
+ if (result != ValidationResult.OK)
+ throw TransactionsResource.createTransactionInvalidException(request, result);
+
+ byte[] bytes = GroupApprovalTransactionTransformer.toBytes(transactionData);
+ return Base58.encode(bytes);
+ } catch (TransformationException e) {
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
+ } catch (DataException e) {
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+ }
+ }
+
+ @POST
+ @Path("/setdefault")
+ @Operation(
+ summary = "Build raw, unsigned, SET_GROUP transaction",
+ requestBody = @RequestBody(
+ required = true,
+ content = @Content(
+ mediaType = MediaType.APPLICATION_JSON,
+ schema = @Schema(
+ implementation = SetGroupTransactionData.class
+ )
+ )
+ ),
+ responses = {
+ @ApiResponse(
+ description = "raw, unsigned, SET_GROUP transaction encoded in Base58",
+ content = @Content(
+ mediaType = MediaType.TEXT_PLAIN,
+ schema = @Schema(
+ type = "string"
+ )
+ )
+ )
+ }
+ )
+ @ApiErrors({ApiError.TRANSACTION_INVALID, ApiError.TRANSFORMATION_ERROR, ApiError.REPOSITORY_ISSUE})
+ public String setGroup(SetGroupTransactionData transactionData) {
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ Transaction transaction = Transaction.fromData(repository, transactionData);
+
+ ValidationResult result = transaction.isValidUnconfirmed();
+ if (result != ValidationResult.OK)
+ throw TransactionsResource.createTransactionInvalidException(request, result);
+
+ byte[] bytes = SetGroupTransactionTransformer.toBytes(transactionData);
+ return Base58.encode(bytes);
+ } catch (TransformationException e) {
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.TRANSFORMATION_ERROR, e);
+ } catch (DataException e) {
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+ }
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/org/qora/api/resource/TransactionsResource.java b/src/main/java/org/qora/api/resource/TransactionsResource.java
index 2fc00393..d81217e1 100644
--- a/src/main/java/org/qora/api/resource/TransactionsResource.java
+++ b/src/main/java/org/qora/api/resource/TransactionsResource.java
@@ -225,6 +225,58 @@ public class TransactionsResource {
}
}
+ @GET
+ @Path("/pending")
+ @Operation(
+ summary = "List transactions pending group approval",
+ description = "Returns transactions that are pending group-admin approval",
+ responses = {
+ @ApiResponse(
+ description = "transactions",
+ content = @Content(
+ array = @ArraySchema(
+ schema = @Schema(
+ implementation = TransactionData.class
+ )
+ )
+ )
+ )
+ }
+ )
+ @ApiErrors({
+ ApiError.REPOSITORY_ISSUE
+ })
+ public List getPendingTransactions(@QueryParam("groupId") Integer groupId, @Parameter(
+ ref = "limit"
+ ) @QueryParam("limit") Integer limit, @Parameter(
+ ref = "offset"
+ ) @QueryParam("offset") Integer offset, @Parameter(
+ ref = "reverse"
+ ) @QueryParam("reverse") Boolean reverse) {
+ try (final Repository repository = RepositoryManager.getRepository()) {
+ List transactions = repository.getTransactionRepository().getUnconfirmedTransactions(null, null, reverse);
+
+ transactions.removeIf(transactionData -> {
+ if (groupId != null && groupId != transactionData.getTxGroupId())
+ return true;
+
+ try {
+ return !Transaction.fromData(repository, transactionData).needsGroupApproval();
+ } catch (DataException e) {
+ return true;
+ }
+ });
+
+ // Results slicing
+
+ return transactions;
+ } catch (ApiException e) {
+ throw e;
+ } catch (DataException e) {
+ throw ApiExceptionFactory.INSTANCE.createException(request, ApiError.REPOSITORY_ISSUE, e);
+ }
+ }
+
public enum ConfirmationStatus {
CONFIRMED,
UNCONFIRMED,
diff --git a/src/main/java/org/qora/at/AT.java b/src/main/java/org/qora/at/AT.java
index 06706074..e8ec2425 100644
--- a/src/main/java/org/qora/at/AT.java
+++ b/src/main/java/org/qora/at/AT.java
@@ -13,7 +13,7 @@ import org.qora.data.transaction.DeployAtTransactionData;
import org.qora.repository.ATRepository;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
-import org.qora.transaction.ATTransaction;
+import org.qora.transaction.AtTransaction;
public class AT {
@@ -38,7 +38,7 @@ public class AT {
public AT(Repository repository, DeployAtTransactionData deployATTransactionData) throws DataException {
this.repository = repository;
- String atAddress = deployATTransactionData.getATAddress();
+ String atAddress = deployATTransactionData.getAtAddress();
int height = this.repository.getBlockRepository().getBlockchainHeight() + 1;
byte[] creatorPublicKey = deployATTransactionData.getCreatorPublicKey();
long creation = deployATTransactionData.getTimestamp();
@@ -126,7 +126,7 @@ public class AT {
this.repository.getATRepository().delete(this.atData.getATAddress());
}
- public List run(long blockTimestamp) throws DataException {
+ public List run(long blockTimestamp) throws DataException {
String atAddress = this.atData.getATAddress();
QoraATAPI api = new QoraATAPI(repository, this.atData, blockTimestamp);
diff --git a/src/main/java/org/qora/at/BlockchainAPI.java b/src/main/java/org/qora/at/BlockchainAPI.java
index f1c2a0dc..4a863902 100644
--- a/src/main/java/org/qora/at/BlockchainAPI.java
+++ b/src/main/java/org/qora/at/BlockchainAPI.java
@@ -28,10 +28,11 @@ public enum BlockchainAPI {
int sequence = timestamp.transactionSequence + 1;
QoraATAPI api = (QoraATAPI) state.getAPI();
- Account recipientAccount = new Account(api.repository, recipient);
BlockRepository blockRepository = api.repository.getBlockRepository();
try {
+ Account recipientAccount = new Account(api.repository, recipient);
+
while (height <= blockRepository.getBlockchainHeight()) {
BlockData blockData = blockRepository.fromHeight(height);
diff --git a/src/main/java/org/qora/at/QoraATAPI.java b/src/main/java/org/qora/at/QoraATAPI.java
index 2b124877..d650e5dd 100644
--- a/src/main/java/org/qora/at/QoraATAPI.java
+++ b/src/main/java/org/qora/at/QoraATAPI.java
@@ -22,9 +22,10 @@ import org.qora.data.block.BlockData;
import org.qora.data.transaction.ATTransactionData;
import org.qora.data.transaction.MessageTransactionData;
import org.qora.data.transaction.TransactionData;
+import org.qora.group.Group;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
-import org.qora.transaction.ATTransaction;
+import org.qora.transaction.AtTransaction;
import com.google.common.primitives.Bytes;
@@ -42,20 +43,20 @@ public class QoraATAPI extends API {
long blockTimestamp;
/** List of generated AT transactions */
- List transactions;
+ List transactions;
// Constructors
public QoraATAPI(Repository repository, ATData atData, long blockTimestamp) {
this.repository = repository;
this.atData = atData;
- this.transactions = new ArrayList();
+ this.transactions = new ArrayList();
this.blockTimestamp = blockTimestamp;
}
// Methods specific to Qora AT processing, not inherited
- public List getTransactions() {
+ public List getTransactions() {
return this.transactions;
}
@@ -248,9 +249,9 @@ public class QoraATAPI extends API {
@Override
public long getCurrentBalance(MachineState state) {
- Account atAccount = this.getATAccount();
-
try {
+ Account atAccount = this.getATAccount();
+
return atAccount.getConfirmedBalance(Asset.QORA).unscaledValue().longValue();
} catch (DataException e) {
throw new RuntimeException("AT API unable to fetch AT's current balance?", e);
@@ -267,9 +268,9 @@ public class QoraATAPI extends API {
byte[] reference = this.getLastReference();
BigDecimal amount = BigDecimal.valueOf(unscaledAmount, 8);
- ATTransactionData atTransactionData = new ATTransactionData(this.atData.getATAddress(), recipient.getAddress(), amount, this.atData.getAssetId(),
- new byte[0], BigDecimal.ZERO.setScale(8), timestamp, reference);
- ATTransaction atTransaction = new ATTransaction(this.repository, atTransactionData);
+ ATTransactionData atTransactionData = new ATTransactionData(timestamp, Group.DEFAULT_GROUP, reference, this.atData.getATAddress(),
+ recipient.getAddress(), amount, this.atData.getAssetId(), new byte[0], BigDecimal.ZERO.setScale(8));
+ AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData);
// Add to our transactions
this.transactions.add(atTransaction);
@@ -285,9 +286,9 @@ public class QoraATAPI extends API {
long timestamp = this.getNextTransactionTimestamp();
byte[] reference = this.getLastReference();
- ATTransactionData atTransactionData = new ATTransactionData(this.atData.getATAddress(), recipient.getAddress(), BigDecimal.ZERO,
- this.atData.getAssetId(), message, BigDecimal.ZERO.setScale(8), timestamp, reference);
- ATTransaction atTransaction = new ATTransaction(this.repository, atTransactionData);
+ ATTransactionData atTransactionData = new ATTransactionData(timestamp, Group.DEFAULT_GROUP, reference,
+ this.atData.getATAddress(), recipient.getAddress(), BigDecimal.ZERO, this.atData.getAssetId(), message, BigDecimal.ZERO.setScale(8));
+ AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData);
// Add to our transactions
this.transactions.add(atTransaction);
@@ -311,9 +312,9 @@ public class QoraATAPI extends API {
byte[] reference = this.getLastReference();
BigDecimal amount = BigDecimal.valueOf(finalBalance, 8);
- ATTransactionData atTransactionData = new ATTransactionData(this.atData.getATAddress(), creator.getAddress(), amount, this.atData.getAssetId(),
- new byte[0], BigDecimal.ZERO.setScale(8), timestamp, reference);
- ATTransaction atTransaction = new ATTransaction(this.repository, atTransactionData);
+ ATTransactionData atTransactionData = new ATTransactionData(timestamp, Group.DEFAULT_GROUP, reference, this.atData.getATAddress(),
+ creator.getAddress(), amount, this.atData.getAssetId(), new byte[0], BigDecimal.ZERO.setScale(8));
+ AtTransaction atTransaction = new AtTransaction(this.repository, atTransactionData);
// Add to our transactions
this.transactions.add(atTransaction);
@@ -422,10 +423,10 @@ public class QoraATAPI extends API {
if (!this.transactions.isEmpty())
return this.transactions.get(this.transactions.size() - 1).getTransactionData().getSignature();
- // No transactions yet, so look up AT's account's last reference from repository
- Account atAccount = this.getATAccount();
-
try {
+ // No transactions yet, so look up AT's account's last reference from repository
+ Account atAccount = this.getATAccount();
+
return atAccount.getLastReference();
} catch (DataException e) {
throw new RuntimeException("AT API unable to fetch AT's last reference from repository?", e);
diff --git a/src/main/java/org/qora/block/Block.java b/src/main/java/org/qora/block/Block.java
index b5f8ecc4..9fcb18fa 100644
--- a/src/main/java/org/qora/block/Block.java
+++ b/src/main/java/org/qora/block/Block.java
@@ -28,7 +28,7 @@ import org.qora.repository.ATRepository;
import org.qora.repository.BlockRepository;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
-import org.qora.transaction.ATTransaction;
+import org.qora.transaction.AtTransaction;
import org.qora.transaction.GenesisTransaction;
import org.qora.transaction.Transaction;
import org.qora.transform.TransformationException;
@@ -706,7 +706,7 @@ public class Block {
* Performs various tests like checking for parent block, correct block timestamp, version, generating balance, etc.
*
* Checks block's transactions by testing their validity then processing them.
- * Hence calls repository.discardChanges() before returning.
+ * Hence uses a repository savepoint during execution.
*
* @return ValidationResult.OK if block is valid, or some other ValidationResult otherwise.
* @throws DataException
@@ -895,7 +895,7 @@ public class Block {
throw new IllegalStateException("Attempted to execute ATs when block's local AT state data already exists");
// AT-Transactions generated by running ATs, to be prepended to block's transactions
- List allATTransactions = new ArrayList();
+ List allATTransactions = new ArrayList();
this.ourAtStates = new ArrayList();
this.ourAtFees = BigDecimal.ZERO.setScale(8);
@@ -906,7 +906,7 @@ public class Block {
// Run each AT, appends AT-Transactions and corresponding AT states, to our lists
for (ATData atData : executableATs) {
AT at = new AT(this.repository, atData);
- List atTransactions = at.run(this.blockData.getTimestamp());
+ List atTransactions = at.run(this.blockData.getTimestamp());
allATTransactions.addAll(atTransactions);
@@ -1005,7 +1005,8 @@ public class Block {
this.repository.getBlockRepository().delete(blockTransactionData);
// Add to unconfirmed pile
- this.repository.getTransactionRepository().unconfirmTransaction(transaction.getTransactionData());
+ // XXX WE CAN'T ADD TO UNCONFIRMED AS TRANSACTION HAS BEEN DELETED BY transaction.orphan() ABOVE
+ // this.repository.getTransactionRepository().unconfirmTransaction(transaction.getTransactionData());
this.repository.getTransactionRepository().deleteParticipants(transaction.getTransactionData());
}
diff --git a/src/main/java/org/qora/block/BlockChain.java b/src/main/java/org/qora/block/BlockChain.java
index 4835cad3..4fee23fe 100644
--- a/src/main/java/org/qora/block/BlockChain.java
+++ b/src/main/java/org/qora/block/BlockChain.java
@@ -13,6 +13,7 @@ import org.apache.logging.log4j.Logger;
import org.json.simple.JSONObject;
import org.qora.data.asset.AssetData;
import org.qora.data.block.BlockData;
+import org.qora.group.Group;
import org.qora.repository.BlockRepository;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
@@ -48,6 +49,10 @@ public class BlockChain {
private long maxBlockTime;
/** Maximum acceptable timestamp disagreement offset in milliseconds. */
private long blockTimestampMargin;
+ /** Whether transactions with txGroupId of NO_GROUP are allowed */
+ private boolean grouplessAllowed;
+ /** Default groupID when txGroupID and account's default groupID are both zero */
+ private int defaultGroupId = Group.NO_GROUP;
/** Map of which blockchain features are enabled when (height/timestamp) */
private Map> featureTriggers;
@@ -101,6 +106,14 @@ public class BlockChain {
return this.blockTimestampMargin;
}
+ public boolean getGrouplessAllowed() {
+ return this.grouplessAllowed;
+ }
+
+ public int getDefaultGroupId() {
+ return this.defaultGroupId;
+ }
+
public static boolean getUseBrokenMD160ForAddresses() {
return useBrokenMD160ForAddresses;
}
@@ -166,6 +179,22 @@ public class BlockChain {
GenesisBlock.fromJSON((JSONObject) genesisJson);
// Simple blockchain properties
+
+ boolean grouplessAllowed = true;
+ if (json.containsKey("grouplessAllowed"))
+ grouplessAllowed = (Boolean) Settings.getTypedJson(json, "grouplessAllowed", Boolean.class);
+
+ Integer defaultGroupId = null;
+ if (json.containsKey("defaultGroupId"))
+ defaultGroupId = ((Long) Settings.getTypedJson(json, "defaultGroupId", Long.class)).intValue();
+
+ // If groupless is not allowed the defaultGroupId needs to be set
+ // XXX we could also check groupID exists, or at least created in genesis block, or in blockchain config
+ if (!grouplessAllowed && (defaultGroupId == null || defaultGroupId == Group.DEFAULT_GROUP || defaultGroupId == Group.NO_GROUP)) {
+ LOGGER.error("defaultGroupId must be set to valid groupID in blockchain config if groupless transactions are not allowed");
+ throw new RuntimeException("defaultGroupId must be set to valid groupID in blockchain config if groupless transactions are not allowed");
+ }
+
BigDecimal unitFee = Settings.getJsonBigDecimal(json, "unitFee");
long maxBytesPerUnitFee = (Long) Settings.getTypedJson(json, "maxBytesPerUnitFee", Long.class);
BigDecimal maxBalance = Settings.getJsonBigDecimal(json, "coinSupply");
@@ -208,6 +237,9 @@ public class BlockChain {
instance.minBlockTime = minBlockTime;
instance.maxBlockTime = maxBlockTime;
instance.blockTimestampMargin = blockTimestampMargin;
+ instance.grouplessAllowed = grouplessAllowed;
+ if (defaultGroupId != null)
+ instance.defaultGroupId = defaultGroupId;
instance.featureTriggers = featureTriggers;
}
diff --git a/src/main/java/org/qora/block/BlockGenerator.java b/src/main/java/org/qora/block/BlockGenerator.java
index 00871c35..d210a3ad 100644
--- a/src/main/java/org/qora/block/BlockGenerator.java
+++ b/src/main/java/org/qora/block/BlockGenerator.java
@@ -85,6 +85,9 @@ public class BlockGenerator extends Thread {
try {
// Is new block valid yet? (Before adding unconfirmed transactions)
if (newBlock.isValid() == ValidationResult.OK) {
+ // Delete invalid transactions
+ deleteInvalidTransactions(repository);
+
// Add unconfirmed transactions
addUnconfirmedTransactions(repository, newBlock);
@@ -131,6 +134,17 @@ public class BlockGenerator extends Thread {
}
}
+ private void deleteInvalidTransactions(Repository repository) throws DataException {
+ List invalidTransactions = Transaction.getInvalidTransactions(repository);
+
+ // Actually delete invalid transactions from database
+ for (TransactionData invalidTransactionData : invalidTransactions) {
+ LOGGER.trace(String.format("Deleting invalid, unconfirmed transaction %s", Base58.encode(invalidTransactionData.getSignature())));
+ repository.getTransactionRepository().delete(invalidTransactionData);
+ }
+ repository.saveChanges();
+ }
+
private void addUnconfirmedTransactions(Repository repository, Block newBlock) throws DataException {
// Grab all valid unconfirmed transactions (already sorted)
List unconfirmedTransactions = Transaction.getUnconfirmedTransactions(repository);
@@ -153,10 +167,17 @@ public class BlockGenerator extends Thread {
--i;
continue;
}
+
+ // Ignore transactions that have not met group-admin approval threshold
+ if (transaction.needsGroupApproval()) {
+ unconfirmedTransactions.remove(i);
+ --i;
+ continue;
+ }
}
- // Discard last-reference changes used to aid transaction validity checks
- repository.discardChanges();
+ // Discard any repository changes used to aid transaction validity checks
+ // repository.discardChanges(); // XXX possibly not needed any more thanks to savepoints?
// Attempt to add transactions until block is full, or we run out
// If a transaction makes the block invalid then skip it and it'll either expire or be in next block.
diff --git a/src/main/java/org/qora/block/GenesisBlock.java b/src/main/java/org/qora/block/GenesisBlock.java
index 208b2e83..8cff5d8c 100644
--- a/src/main/java/org/qora/block/GenesisBlock.java
+++ b/src/main/java/org/qora/block/GenesisBlock.java
@@ -98,9 +98,9 @@ public class GenesisBlock extends Block {
// We're into version 4 genesis block territory now
version = 4;
- transactions.add(new GenesisTransactionData(recipient, amount, assetId, timestamp));
+ transactions.add(new GenesisTransactionData(timestamp, recipient, amount, assetId));
} else {
- transactions.add(new GenesisTransactionData(recipient, amount, timestamp));
+ transactions.add(new GenesisTransactionData(timestamp, recipient, amount));
}
}
diff --git a/src/main/java/org/qora/controller/Synchronizer.java b/src/main/java/org/qora/controller/Synchronizer.java
index 7504d8c9..b8acc483 100644
--- a/src/main/java/org/qora/controller/Synchronizer.java
+++ b/src/main/java/org/qora/controller/Synchronizer.java
@@ -136,7 +136,7 @@ public class Synchronizer {
return true;
} finally {
- repository.discardChanges();
+ repository.discardChanges(); // Free repository locks, if any, also in case anything went wrong
this.repository = null;
}
}
diff --git a/src/main/java/org/qora/data/account/AccountBalanceData.java b/src/main/java/org/qora/data/account/AccountBalanceData.java
index c582b559..1f1ed3e4 100644
--- a/src/main/java/org/qora/data/account/AccountBalanceData.java
+++ b/src/main/java/org/qora/data/account/AccountBalanceData.java
@@ -5,7 +5,7 @@ import java.math.BigDecimal;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
public class AccountBalanceData {
@@ -16,9 +16,8 @@ public class AccountBalanceData {
// Constructors
- // necessary for JAX-RS serialization
- @SuppressWarnings("unused")
- private AccountBalanceData() {
+ // necessary for JAXB
+ protected AccountBalanceData() {
}
public AccountBalanceData(String address, long assetId, BigDecimal balance) {
diff --git a/src/main/java/org/qora/data/account/AccountData.java b/src/main/java/org/qora/data/account/AccountData.java
index 269c0b3b..15b5fbb3 100644
--- a/src/main/java/org/qora/data/account/AccountData.java
+++ b/src/main/java/org/qora/data/account/AccountData.java
@@ -1,22 +1,35 @@
package org.qora.data.account;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+import org.qora.group.Group;
+
+// All properties to be converted to JSON via JAXB
+@XmlAccessorType(XmlAccessType.FIELD)
public class AccountData {
// Properties
protected String address;
protected byte[] reference;
protected byte[] publicKey;
+ protected int defaultGroupId;
// Constructors
- public AccountData(String address, byte[] reference, byte[] publicKey) {
+ // For JAXB
+ protected AccountData() {
+ }
+
+ public AccountData(String address, byte[] reference, byte[] publicKey, int defaultGroupId) {
this.address = address;
this.reference = reference;
this.publicKey = publicKey;
+ this.defaultGroupId = defaultGroupId;
}
public AccountData(String address) {
- this(address, null, null);
+ this(address, null, null, Group.DEFAULT_GROUP);
}
// Getters/Setters
@@ -41,6 +54,14 @@ public class AccountData {
this.publicKey = publicKey;
}
+ public int getDefaultGroupId() {
+ return this.defaultGroupId;
+ }
+
+ public void setDefaultGroupId(int defaultGroupId) {
+ this.defaultGroupId = defaultGroupId;
+ }
+
// Comparison
@Override
diff --git a/src/main/java/org/qora/data/group/GroupData.java b/src/main/java/org/qora/data/group/GroupData.java
index 9b6350bc..09a487c0 100644
--- a/src/main/java/org/qora/data/group/GroupData.java
+++ b/src/main/java/org/qora/data/group/GroupData.java
@@ -4,6 +4,8 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
+import org.qora.group.Group.ApprovalThreshold;
+
import io.swagger.v3.oas.annotations.media.Schema;
// All properties to be converted to JSON via JAX-RS
@@ -18,6 +20,7 @@ public class GroupData {
private long created;
private Long updated;
private boolean isOpen;
+ private ApprovalThreshold approvalThreshold;
/** Reference to CREATE_GROUP or UPDATE_GROUP transaction, used to rebuild group during orphaning. */
// No need to ever expose this via API
@XmlTransient
@@ -31,7 +34,7 @@ public class GroupData {
}
/** Constructs new GroupData with nullable groupId and nullable updated [timestamp] */
- public GroupData(Integer groupId, String owner, String name, String description, long created, Long updated, boolean isOpen, byte[] reference) {
+ public GroupData(Integer groupId, String owner, String name, String description, long created, Long updated, boolean isOpen, ApprovalThreshold approvalThreshold, byte[] reference) {
this.groupId = groupId;
this.owner = owner;
this.groupName = name;
@@ -39,12 +42,13 @@ public class GroupData {
this.created = created;
this.updated = updated;
this.isOpen = isOpen;
+ this.approvalThreshold = approvalThreshold;
this.reference = reference;
}
/** Constructs new GroupData with unassigned groupId */
- public GroupData(String owner, String name, String description, long created, boolean isOpen, byte[] reference) {
- this(null, owner, name, description, created, null, isOpen, reference);
+ public GroupData(String owner, String name, String description, long created, boolean isOpen, ApprovalThreshold approvalThreshold, byte[] reference) {
+ this(null, owner, name, description, created, null, isOpen, approvalThreshold, reference);
}
// Getters / setters
@@ -105,4 +109,12 @@ public class GroupData {
this.isOpen = isOpen;
}
+ public ApprovalThreshold getApprovalThreshold() {
+ return this.approvalThreshold;
+ }
+
+ public void setApprovalThreshold(ApprovalThreshold approvalThreshold) {
+ this.approvalThreshold = approvalThreshold;
+ }
+
}
diff --git a/src/main/java/org/qora/data/transaction/ATTransactionData.java b/src/main/java/org/qora/data/transaction/ATTransactionData.java
index 19367ec5..ee409669 100644
--- a/src/main/java/org/qora/data/transaction/ATTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/ATTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -10,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class ATTransactionData extends TransactionData {
@@ -24,13 +25,18 @@ public class ATTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected ATTransactionData() {
+ super(TransactionType.AT);
}
- public ATTransactionData(String atAddress, String recipient, BigDecimal amount, Long assetId, byte[] message, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- super(TransactionType.AT, fee, GenesisAccount.PUBLIC_KEY, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = GenesisAccount.PUBLIC_KEY;
+ }
+
+ public ATTransactionData(long timestamp, int txGroupId, byte[] reference, String atAddress, String recipient, BigDecimal amount, Long assetId,
+ byte[] message, BigDecimal fee, byte[] signature) {
+ super(TransactionType.AT, timestamp, txGroupId, reference, GenesisAccount.PUBLIC_KEY, fee, signature);
this.atAddress = atAddress;
this.recipient = recipient;
@@ -39,9 +45,9 @@ public class ATTransactionData extends TransactionData {
this.message = message;
}
- public ATTransactionData(String atAddress, String recipient, BigDecimal amount, Long assetId, byte[] message, BigDecimal fee, long timestamp,
- byte[] reference) {
- this(atAddress, recipient, amount, assetId, message, fee, timestamp, reference, null);
+ public ATTransactionData(long timestamp, int txGroupId, byte[] reference, String atAddress, String recipient, BigDecimal amount, Long assetId,
+ byte[] message, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, atAddress, recipient, amount, assetId, message, fee, null);
}
// Getters/Setters
diff --git a/src/main/java/org/qora/data/transaction/AddGroupAdminTransactionData.java b/src/main/java/org/qora/data/transaction/AddGroupAdminTransactionData.java
index 876e2b48..e29bf2fc 100644
--- a/src/main/java/org/qora/data/transaction/AddGroupAdminTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/AddGroupAdminTransactionData.java
@@ -10,7 +10,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class AddGroupAdminTransactionData extends TransactionData {
@@ -25,7 +25,7 @@ public class AddGroupAdminTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected AddGroupAdminTransactionData() {
super(TransactionType.ADD_GROUP_ADMIN);
}
@@ -34,8 +34,8 @@ public class AddGroupAdminTransactionData extends TransactionData {
this.creatorPublicKey = this.ownerPublicKey;
}
- public AddGroupAdminTransactionData(byte[] ownerPublicKey, int groupId, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.ADD_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature);
+ public AddGroupAdminTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, int groupId, String member, BigDecimal fee, byte[] signature) {
+ super(TransactionType.ADD_GROUP_ADMIN, timestamp, txGroupId, reference, ownerPublicKey, fee, signature);
this.ownerPublicKey = ownerPublicKey;
this.groupId = groupId;
diff --git a/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java b/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java
index f7582d53..c2d42384 100644
--- a/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/ArbitraryTransactionData.java
@@ -3,6 +3,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
import java.util.List;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -11,7 +12,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class ArbitraryTransactionData extends TransactionData {
@@ -32,17 +33,22 @@ public class ArbitraryTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected ArbitraryTransactionData() {
+ super(TransactionType.ARBITRARY);
+ }
+
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.senderPublicKey;
}
/** Reconstructing a V3 arbitrary transaction with signature */
- public ArbitraryTransactionData(int version, byte[] senderPublicKey, int service, byte[] data, DataType dataType, List payments,
- BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.ARBITRARY, fee, senderPublicKey, timestamp, reference, signature);
+ public ArbitraryTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, int version, int service,
+ byte[] data, DataType dataType, List payments, BigDecimal fee, byte[] signature) {
+ super(TransactionType.ARBITRARY, timestamp, txGroupId, reference, senderPublicKey, fee, signature);
- this.version = version;
this.senderPublicKey = senderPublicKey;
+ this.version = version;
this.service = service;
this.data = data;
this.dataType = dataType;
@@ -50,33 +56,33 @@ public class ArbitraryTransactionData extends TransactionData {
}
/** Constructing a new V3 arbitrary transaction without signature */
- public ArbitraryTransactionData(int version, byte[] senderPublicKey, int service, byte[] data, DataType dataType, List payments,
- BigDecimal fee, long timestamp, byte[] reference) {
- this(version, senderPublicKey, service, data, dataType, payments, fee, timestamp, reference, null);
+ public ArbitraryTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, int version, int service,
+ byte[] data, DataType dataType, List payments, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, senderPublicKey, version, service, data, dataType, payments, fee, null);
}
/** Reconstructing a V1 arbitrary transaction with signature */
- public ArbitraryTransactionData(int version, byte[] senderPublicKey, int service, byte[] data, DataType dataType, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- this(version, senderPublicKey, service, data, dataType, null, fee, timestamp, reference, signature);
+ public ArbitraryTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, int version, int service, byte[] data,
+ DataType dataType, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, senderPublicKey, version, service, data, dataType, null, fee, signature);
}
/** Constructing a new V1 arbitrary transaction without signature */
- public ArbitraryTransactionData(int version, byte[] senderPublicKey, int service, byte[] data, DataType dataType, BigDecimal fee, long timestamp,
- byte[] reference) {
- this(version, senderPublicKey, service, data, dataType, null, fee, timestamp, reference, null);
+ public ArbitraryTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, int version, int service, byte[] data,
+ DataType dataType, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, senderPublicKey, version, service, data, dataType, null, fee, null);
}
// Getters/Setters
- public int getVersion() {
- return this.version;
- }
-
public byte[] getSenderPublicKey() {
return this.senderPublicKey;
}
+ public int getVersion() {
+ return this.version;
+ }
+
public int getService() {
return this.service;
}
diff --git a/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java b/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java
index 27bde460..8f98253c 100644
--- a/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/BuyNameTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
@@ -11,7 +12,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class BuyNameTransactionData extends TransactionData {
@@ -36,14 +37,18 @@ public class BuyNameTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected BuyNameTransactionData() {
super(TransactionType.BUY_NAME);
}
- public BuyNameTransactionData(byte[] buyerPublicKey, String name, BigDecimal amount, String seller, byte[] nameReference, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- super(TransactionType.BUY_NAME, fee, buyerPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.buyerPublicKey;
+ }
+
+ public BuyNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] buyerPublicKey, String name, BigDecimal amount, String seller,
+ byte[] nameReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.BUY_NAME, timestamp, txGroupId, reference, buyerPublicKey, fee, signature);
this.buyerPublicKey = buyerPublicKey;
this.name = name;
@@ -52,18 +57,18 @@ public class BuyNameTransactionData extends TransactionData {
this.nameReference = nameReference;
}
- public BuyNameTransactionData(byte[] buyerPublicKey, String name, BigDecimal amount, String seller, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- this(buyerPublicKey, name, amount, seller, null, fee, timestamp, reference, signature);
+ public BuyNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] buyerPublicKey, String name, BigDecimal amount, String seller,
+ BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, buyerPublicKey, name, amount, seller, null, fee, signature);
}
- public BuyNameTransactionData(byte[] buyerPublicKey, String name, BigDecimal amount, String seller, byte[] nameReference, BigDecimal fee, long timestamp,
- byte[] reference) {
- this(buyerPublicKey, name, amount, seller, nameReference, fee, timestamp, reference, null);
+ public BuyNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] buyerPublicKey, String name, BigDecimal amount, String seller,
+ byte[] nameReference, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, buyerPublicKey, name, amount, seller, nameReference, fee, null);
}
- public BuyNameTransactionData(byte[] buyerPublicKey, String name, BigDecimal amount, String seller, BigDecimal fee, long timestamp, byte[] reference) {
- this(buyerPublicKey, name, amount, seller, null, fee, timestamp, reference, null);
+ public BuyNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] buyerPublicKey, String name, BigDecimal amount, String seller, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, buyerPublicKey, name, amount, seller, null, fee, null);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java b/src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java
index 1d1021ef..514114f4 100644
--- a/src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CancelAssetOrderTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CancelAssetOrderTransactionData extends TransactionData {
@@ -22,19 +22,19 @@ public class CancelAssetOrderTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected CancelAssetOrderTransactionData() {
super(TransactionType.CANCEL_ASSET_ORDER);
}
- 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);
+ public CancelAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, byte[] signature) {
+ super(Transaction.TransactionType.CANCEL_ASSET_ORDER, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
this.orderId = orderId;
}
- public CancelAssetOrderTransactionData(byte[] creatorPublicKey, byte[] orderId, BigDecimal fee, long timestamp, byte[] reference) {
- this(creatorPublicKey, orderId, fee, timestamp, reference, null);
+ public CancelAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, byte[] orderId, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, creatorPublicKey, orderId, fee, null);
}
// Getters/Setters
diff --git a/src/main/java/org/qora/data/transaction/CancelGroupBanTransactionData.java b/src/main/java/org/qora/data/transaction/CancelGroupBanTransactionData.java
index 3ce5afd7..f20d8a56 100644
--- a/src/main/java/org/qora/data/transaction/CancelGroupBanTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CancelGroupBanTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CancelGroupBanTransactionData extends TransactionData {
@@ -31,7 +31,7 @@ public class CancelGroupBanTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected CancelGroupBanTransactionData() {
super(TransactionType.CANCEL_GROUP_BAN);
}
@@ -40,8 +40,8 @@ public class CancelGroupBanTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey;
}
- public CancelGroupBanTransactionData(byte[] adminPublicKey, int groupId, String member, byte[] banReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.CANCEL_GROUP_BAN, fee, adminPublicKey, timestamp, reference, signature);
+ public CancelGroupBanTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String member, byte[] banReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.CANCEL_GROUP_BAN, timestamp, txGroupId, reference, adminPublicKey, fee, signature);
this.adminPublicKey = adminPublicKey;
this.groupId = groupId;
@@ -50,8 +50,8 @@ public class CancelGroupBanTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public CancelGroupBanTransactionData(byte[] adminPublicKey, int groupId, String member, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(adminPublicKey, groupId, member, null, fee, timestamp, reference, signature);
+ public CancelGroupBanTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String member, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, adminPublicKey, groupId, member, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/CancelGroupInviteTransactionData.java b/src/main/java/org/qora/data/transaction/CancelGroupInviteTransactionData.java
index 646f3664..35dbaca0 100644
--- a/src/main/java/org/qora/data/transaction/CancelGroupInviteTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CancelGroupInviteTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CancelGroupInviteTransactionData extends TransactionData {
@@ -31,7 +31,7 @@ public class CancelGroupInviteTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected CancelGroupInviteTransactionData() {
super(TransactionType.CANCEL_GROUP_INVITE);
}
@@ -40,8 +40,8 @@ public class CancelGroupInviteTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey;
}
- public CancelGroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, byte[] inviteReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.CANCEL_GROUP_INVITE, fee, adminPublicKey, timestamp, reference, signature);
+ public CancelGroupInviteTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String invitee, byte[] inviteReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.CANCEL_GROUP_INVITE, timestamp, txGroupId, reference, adminPublicKey, fee, signature);
this.adminPublicKey = adminPublicKey;
this.groupId = groupId;
@@ -50,8 +50,8 @@ public class CancelGroupInviteTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public CancelGroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(adminPublicKey, groupId, invitee, null, fee, timestamp, reference, signature);
+ public CancelGroupInviteTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String invitee, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, adminPublicKey, groupId, invitee, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java b/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java
index e55da8c9..3372c298 100644
--- a/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CancelSellNameTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -9,7 +10,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CancelSellNameTransactionData extends TransactionData {
@@ -22,20 +23,24 @@ public class CancelSellNameTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected CancelSellNameTransactionData() {
super(TransactionType.CANCEL_SELL_NAME);
}
- public CancelSellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.CANCEL_SELL_NAME, fee, ownerPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.ownerPublicKey;
+ }
+
+ public CancelSellNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String name, BigDecimal fee, byte[] signature) {
+ super(TransactionType.CANCEL_SELL_NAME, timestamp, txGroupId, reference, ownerPublicKey, fee, signature);
this.ownerPublicKey = ownerPublicKey;
this.name = name;
}
- public CancelSellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal fee, long timestamp, byte[] reference) {
- this(ownerPublicKey, name, fee, timestamp, reference, null);
+ public CancelSellNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String name, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, ownerPublicKey, name, fee, null);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java b/src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java
index ef232e9b..5b9e148f 100644
--- a/src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CreateAssetOrderTransactionData.java
@@ -10,7 +10,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CreateAssetOrderTransactionData extends TransactionData {
@@ -27,14 +27,14 @@ public class CreateAssetOrderTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected CreateAssetOrderTransactionData() {
super(TransactionType.CREATE_ASSET_ORDER);
}
- 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);
+ public CreateAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, long haveAssetId, long wantAssetId,
+ BigDecimal amount, BigDecimal price, BigDecimal fee, byte[] signature) {
+ super(TransactionType.CREATE_ASSET_ORDER, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
this.haveAssetId = haveAssetId;
this.wantAssetId = wantAssetId;
@@ -42,9 +42,9 @@ public class CreateAssetOrderTransactionData extends TransactionData {
this.price = price;
}
- 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);
+ public CreateAssetOrderTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, long haveAssetId, long wantAssetId,
+ BigDecimal amount, BigDecimal price, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, null);
}
// Getters/Setters
diff --git a/src/main/java/org/qora/data/transaction/CreateGroupTransactionData.java b/src/main/java/org/qora/data/transaction/CreateGroupTransactionData.java
index 0a4e3a91..a07fc0ee 100644
--- a/src/main/java/org/qora/data/transaction/CreateGroupTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CreateGroupTransactionData.java
@@ -6,12 +6,13 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(
allOf = {
@@ -47,23 +48,28 @@ public class CreateGroupTransactionData extends TransactionData {
example = "true"
)
private boolean isOpen;
+ @Schema(
+ description = "how many group admins are required to approve group member transactions"
+ )
+ private ApprovalThreshold approvalThreshold;
// Constructors
- // For JAX-RS
+ // For JAXB
protected CreateGroupTransactionData() {
super(TransactionType.CREATE_GROUP);
}
- public CreateGroupTransactionData(byte[] creatorPublicKey, String owner, String groupName, String description, boolean isOpen, Integer groupId,
- BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.CREATE_GROUP, fee, creatorPublicKey, timestamp, reference, signature);
+ public CreateGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, String owner, String groupName, String description,
+ boolean isOpen, ApprovalThreshold approvalThreshold, Integer groupId, BigDecimal fee, byte[] signature) {
+ super(TransactionType.CREATE_GROUP, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
this.creatorPublicKey = creatorPublicKey;
this.owner = owner;
this.groupName = groupName;
this.description = description;
this.isOpen = isOpen;
+ this.approvalThreshold = approvalThreshold;
this.groupId = groupId;
}
@@ -85,6 +91,10 @@ public class CreateGroupTransactionData extends TransactionData {
return this.isOpen;
}
+ public ApprovalThreshold getApprovalThreshold() {
+ return this.approvalThreshold;
+ }
+
public Integer getGroupId() {
return this.groupId;
}
diff --git a/src/main/java/org/qora/data/transaction/CreatePollTransactionData.java b/src/main/java/org/qora/data/transaction/CreatePollTransactionData.java
index 9d0cd2f9..69fe05af 100644
--- a/src/main/java/org/qora/data/transaction/CreatePollTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/CreatePollTransactionData.java
@@ -8,10 +8,11 @@ import javax.xml.bind.annotation.XmlAccessorType;
import org.qora.data.voting.PollOptionData;
import org.qora.transaction.Transaction;
+import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class CreatePollTransactionData extends TransactionData {
@@ -24,13 +25,14 @@ public class CreatePollTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected CreatePollTransactionData() {
+ super(TransactionType.CREATE_POLL);
}
- public CreatePollTransactionData(byte[] creatorPublicKey, String owner, String pollName, String description, List pollOptions,
- BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(Transaction.TransactionType.CREATE_POLL, fee, creatorPublicKey, timestamp, reference, signature);
+ public CreatePollTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, String owner,
+ String pollName, String description, List pollOptions, BigDecimal fee, byte[] signature) {
+ super(Transaction.TransactionType.CREATE_POLL, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
this.owner = owner;
this.pollName = pollName;
@@ -38,9 +40,9 @@ public class CreatePollTransactionData extends TransactionData {
this.pollOptions = pollOptions;
}
- public CreatePollTransactionData(byte[] creatorPublicKey, String owner, String pollName, String description, List pollOptions,
- BigDecimal fee, long timestamp, byte[] reference) {
- this(creatorPublicKey, owner, pollName, description, pollOptions, fee, timestamp, reference, null);
+ public CreatePollTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, String owner,
+ String pollName, String description, List pollOptions, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, creatorPublicKey, owner, pollName, description, pollOptions, fee, null);
}
// Getters/setters
diff --git a/src/main/java/org/qora/data/transaction/DeployAtTransactionData.java b/src/main/java/org/qora/data/transaction/DeployAtTransactionData.java
index ebda409c..04e3f681 100644
--- a/src/main/java/org/qora/data/transaction/DeployAtTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/DeployAtTransactionData.java
@@ -9,7 +9,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class DeployAtTransactionData extends TransactionData {
@@ -17,41 +17,42 @@ public class DeployAtTransactionData extends TransactionData {
// Properties
private String name;
private String description;
- private String ATType;
+ private String aTType;
private String tags;
private byte[] creationBytes;
private BigDecimal amount;
private long assetId;
- private String ATAddress;
+ private String aTAddress;
// Constructors
// For JAX-RS
protected DeployAtTransactionData() {
+ super(TransactionType.DEPLOY_AT);
}
- 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);
+ public DeployAtTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, String aTAddress, String name, String description,
+ String aTType, String tags, byte[] creationBytes, BigDecimal amount, long assetId, BigDecimal fee, byte[] signature) {
+ super(TransactionType.DEPLOY_AT, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
+ this.aTAddress = aTAddress;
this.name = name;
this.description = description;
- this.ATType = ATType;
+ this.aTType = aTType;
this.tags = tags;
+ this.creationBytes = creationBytes;
this.amount = amount;
this.assetId = assetId;
- this.creationBytes = creationBytes;
- this.ATAddress = ATAddress;
}
- 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(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, String name, String description,
+ String aTType, String tags, byte[] creationBytes, BigDecimal amount, long assetId, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, creatorPublicKey, null, name, description, aTType, tags, creationBytes, amount, assetId, fee, signature);
}
- 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);
+ public DeployAtTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, String name, String description,
+ String aTType, String tags, byte[] creationBytes, BigDecimal amount, long assetId, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, creatorPublicKey, null, name, description, aTType, tags, creationBytes, amount, assetId, fee, null);
}
// Getters/Setters
@@ -64,8 +65,8 @@ public class DeployAtTransactionData extends TransactionData {
return this.description;
}
- public String getATType() {
- return this.ATType;
+ public String getAtType() {
+ return this.aTType;
}
public String getTags() {
@@ -84,12 +85,12 @@ public class DeployAtTransactionData extends TransactionData {
return this.assetId;
}
- public String getATAddress() {
- return this.ATAddress;
+ public String getAtAddress() {
+ return this.aTAddress;
}
- public void setATAddress(String ATAddress) {
- this.ATAddress = ATAddress;
+ public void setAtAddress(String AtAddress) {
+ this.aTAddress = AtAddress;
}
}
diff --git a/src/main/java/org/qora/data/transaction/GenesisTransactionData.java b/src/main/java/org/qora/data/transaction/GenesisTransactionData.java
index 3a65c5b1..3a1725a0 100644
--- a/src/main/java/org/qora/data/transaction/GenesisTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/GenesisTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(
allOf = {
@@ -27,29 +27,30 @@ public class GenesisTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected GenesisTransactionData() {
+ super(TransactionType.GENESIS);
}
- public GenesisTransactionData(String recipient, BigDecimal amount, long assetId, long timestamp, byte[] signature) {
- // Zero fee
- super(TransactionType.GENESIS, BigDecimal.ZERO, GenesisAccount.PUBLIC_KEY, timestamp, null, signature);
+ public GenesisTransactionData(long timestamp, String recipient, BigDecimal amount, long assetId, byte[] signature) {
+ // no groupID, Zero fee
+ super(TransactionType.GENESIS, timestamp, 0, null, GenesisAccount.PUBLIC_KEY, BigDecimal.ZERO, signature);
this.recipient = recipient;
this.amount = amount;
this.assetId = assetId;
}
- public GenesisTransactionData(String recipient, BigDecimal amount, long timestamp, byte[] signature) {
- this(recipient, amount, Asset.QORA, timestamp, signature);
+ public GenesisTransactionData(long timestamp, String recipient, BigDecimal amount, byte[] signature) {
+ this(timestamp, recipient, amount, Asset.QORA, signature);
}
- public GenesisTransactionData(String recipient, BigDecimal amount, long assetId, long timestamp) {
- this(recipient, amount, assetId, timestamp, null);
+ public GenesisTransactionData(long timestamp, String recipient, BigDecimal amount, long assetId) {
+ this(timestamp, recipient, amount, assetId, null);
}
- public GenesisTransactionData(String recipient, BigDecimal amount, long timestamp) {
- this(recipient, amount, Asset.QORA, timestamp, null);
+ public GenesisTransactionData(long timestamp, String recipient, BigDecimal amount) {
+ this(timestamp, recipient, amount, Asset.QORA, null);
}
// Getters/Setters
diff --git a/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java b/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java
new file mode 100644
index 00000000..384a4143
--- /dev/null
+++ b/src/main/java/org/qora/data/transaction/GroupApprovalTransactionData.java
@@ -0,0 +1,95 @@
+package org.qora.data.transaction;
+
+import java.math.BigDecimal;
+
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.qora.transaction.Transaction.TransactionType;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+// All properties to be converted to JSON via JAXB
+@XmlAccessorType(XmlAccessType.FIELD)
+@Schema(
+ allOf = {
+ TransactionData.class
+ }
+)
+public class GroupApprovalTransactionData extends TransactionData {
+
+ // Properties
+ @Schema(
+ description = "admin's public key",
+ example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP"
+ )
+ private byte[] adminPublicKey;
+ @Schema(
+ description = "transaction pending approval"
+ )
+ private byte[] pendingSignature;
+ @Schema(
+ description = "approval decision",
+ example = "true"
+ )
+ private boolean approval;
+ /** Reference to prior GROUP_APPROVAL transaction, used to rebuild approval status during orphaning. */
+ // For internal use when orphaning
+ @XmlTransient
+ @Schema(
+ hidden = true
+ )
+ private byte[] priorReference;
+
+ // Constructors
+
+ // For JAXB
+ protected GroupApprovalTransactionData() {
+ super(TransactionType.GROUP_APPROVAL);
+ }
+
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.adminPublicKey;
+ }
+
+ public GroupApprovalTransactionData(long timestamp, int groupId, byte[] reference, byte[] adminPublicKey, byte[] pendingSignature, boolean approval,
+ byte[] priorReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.GROUP_APPROVAL, timestamp, groupId, reference, adminPublicKey, fee, signature);
+
+ this.adminPublicKey = adminPublicKey;
+ this.pendingSignature = pendingSignature;
+ this.approval = approval;
+ this.priorReference = priorReference;
+ }
+
+ /** Constructor typically used after deserialization */
+ public GroupApprovalTransactionData(long timestamp, int groupId, byte[] reference, byte[] adminPublicKey, byte[] pendingSignature, boolean approval,
+ BigDecimal fee, byte[] signature) {
+ this(timestamp, groupId, reference, adminPublicKey, pendingSignature, approval, null, fee, signature);
+ }
+
+ // Getters / setters
+
+ public byte[] getAdminPublicKey() {
+ return this.adminPublicKey;
+ }
+
+ public byte[] getPendingSignature() {
+ return this.pendingSignature;
+ }
+
+ public boolean getApproval() {
+ return this.approval;
+ }
+
+ public byte[] getPriorReference() {
+ return this.priorReference;
+ }
+
+ public void setPriorReference(byte[] priorReference) {
+ this.priorReference = priorReference;
+ }
+
+}
diff --git a/src/main/java/org/qora/data/transaction/GroupBanTransactionData.java b/src/main/java/org/qora/data/transaction/GroupBanTransactionData.java
index c8a2fd33..d6710b12 100644
--- a/src/main/java/org/qora/data/transaction/GroupBanTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/GroupBanTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(
allOf = {
@@ -61,7 +61,7 @@ public class GroupBanTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected GroupBanTransactionData() {
super(TransactionType.GROUP_BAN);
}
@@ -70,9 +70,9 @@ public class GroupBanTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey;
}
- public GroupBanTransactionData(byte[] adminPublicKey, int groupId, String member, String reason, int timeToLive, byte[] memberReference,
- byte[] adminReference, byte[] joinInviteReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.GROUP_BAN, fee, adminPublicKey, timestamp, reference, signature);
+ public GroupBanTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String member,
+ String reason, int timeToLive, byte[] memberReference, byte[] adminReference, byte[] joinInviteReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.GROUP_BAN, timestamp, txGroupId, reference, adminPublicKey, fee, signature);
this.adminPublicKey = adminPublicKey;
this.groupId = groupId;
@@ -85,9 +85,9 @@ public class GroupBanTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public GroupBanTransactionData(byte[] adminPublicKey, int groupId, String offender, String reason, int timeToLive, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- this(adminPublicKey, groupId, offender, reason, timeToLive, null, null, null, fee, timestamp, reference, signature);
+ public GroupBanTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String offender, String reason,
+ int timeToLive, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, adminPublicKey, groupId, offender, reason, timeToLive, null, null, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/GroupInviteTransactionData.java b/src/main/java/org/qora/data/transaction/GroupInviteTransactionData.java
index 9f6bfde9..ef9bdbda 100644
--- a/src/main/java/org/qora/data/transaction/GroupInviteTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/GroupInviteTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class GroupInviteTransactionData extends TransactionData {
@@ -33,7 +33,7 @@ public class GroupInviteTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected GroupInviteTransactionData() {
super(TransactionType.GROUP_INVITE);
}
@@ -42,8 +42,8 @@ public class GroupInviteTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey;
}
- public GroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, int timeToLive, byte[] joinReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.GROUP_INVITE, fee, adminPublicKey, timestamp, reference, signature);
+ public GroupInviteTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String invitee, int timeToLive, byte[] joinReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.GROUP_INVITE, timestamp, txGroupId, reference, adminPublicKey, fee, signature);
this.adminPublicKey = adminPublicKey;
this.groupId = groupId;
@@ -53,8 +53,8 @@ public class GroupInviteTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public GroupInviteTransactionData(byte[] adminPublicKey, int groupId, String invitee, int timeToLive, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(adminPublicKey, groupId, invitee, timeToLive, null, fee, timestamp, reference, signature);
+ public GroupInviteTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String invitee, int timeToLive, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, adminPublicKey, groupId, invitee, timeToLive, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/GroupKickTransactionData.java b/src/main/java/org/qora/data/transaction/GroupKickTransactionData.java
index ae4087af..9aa44119 100644
--- a/src/main/java/org/qora/data/transaction/GroupKickTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/GroupKickTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(
allOf = {
@@ -58,7 +58,7 @@ public class GroupKickTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected GroupKickTransactionData() {
super(TransactionType.GROUP_KICK);
}
@@ -67,9 +67,9 @@ public class GroupKickTransactionData extends TransactionData {
this.creatorPublicKey = this.adminPublicKey;
}
- public GroupKickTransactionData(byte[] adminPublicKey, int groupId, String member, String reason, byte[] memberReference, byte[] adminReference,
- byte[] joinReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.GROUP_KICK, fee, adminPublicKey, timestamp, reference, signature);
+ public GroupKickTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String member,
+ String reason, byte[] memberReference, byte[] adminReference, byte[] joinReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.GROUP_KICK, timestamp, txGroupId, reference, adminPublicKey, fee, signature);
this.adminPublicKey = adminPublicKey;
this.groupId = groupId;
@@ -81,9 +81,9 @@ public class GroupKickTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public GroupKickTransactionData(byte[] adminPublicKey, int groupId, String member, String reason, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- this(adminPublicKey, groupId, member, reason, null, null, null, fee, timestamp, reference, signature);
+ public GroupKickTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] adminPublicKey, int groupId, String member, String reason,
+ BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, adminPublicKey, groupId, member, reason, null, null, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java b/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java
index 0dc95174..7e57a665 100644
--- a/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/IssueAssetTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -10,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class IssueAssetTransactionData extends TransactionData {
@@ -34,14 +35,18 @@ public class IssueAssetTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected IssueAssetTransactionData() {
super(TransactionType.ISSUE_ASSET);
}
- public IssueAssetTransactionData(Long assetId, byte[] issuerPublicKey, String owner, String assetName, String description, long quantity,
- boolean isDivisible, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.ISSUE_ASSET, fee, issuerPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.issuerPublicKey;
+ }
+
+ public IssueAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] issuerPublicKey, Long assetId, String owner,
+ String assetName, String description, long quantity, boolean isDivisible, BigDecimal fee, byte[] signature) {
+ super(TransactionType.ISSUE_ASSET, timestamp, txGroupId, reference, issuerPublicKey, fee, signature);
this.assetId = assetId;
this.issuerPublicKey = issuerPublicKey;
@@ -52,14 +57,14 @@ public class IssueAssetTransactionData extends TransactionData {
this.isDivisible = isDivisible;
}
- public IssueAssetTransactionData(byte[] issuerPublicKey, String owner, String assetName, String description, long quantity, boolean isDivisible,
- BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(null, issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, signature);
+ public IssueAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] issuerPublicKey, String owner, String assetName,
+ String description, long quantity, boolean isDivisible, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, issuerPublicKey, null, owner, assetName, description, quantity, isDivisible, fee, signature);
}
- public IssueAssetTransactionData(byte[] issuerPublicKey, String owner, String assetName, String description, long quantity, boolean isDivisible,
- BigDecimal fee, long timestamp, byte[] reference) {
- this(null, issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, null);
+ public IssueAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] issuerPublicKey, String owner, String assetName,
+ String description, long quantity, boolean isDivisible, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, issuerPublicKey, null, owner, assetName, description, quantity, isDivisible, fee, null);
}
// Getters/Setters
diff --git a/src/main/java/org/qora/data/transaction/JoinGroupTransactionData.java b/src/main/java/org/qora/data/transaction/JoinGroupTransactionData.java
index 3e04484b..6059b090 100644
--- a/src/main/java/org/qora/data/transaction/JoinGroupTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/JoinGroupTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class JoinGroupTransactionData extends TransactionData {
@@ -29,7 +29,7 @@ public class JoinGroupTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected JoinGroupTransactionData() {
super(TransactionType.JOIN_GROUP);
}
@@ -38,8 +38,8 @@ public class JoinGroupTransactionData extends TransactionData {
this.creatorPublicKey = this.joinerPublicKey;
}
- public JoinGroupTransactionData(byte[] joinerPublicKey, int groupId, byte[] inviteReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.JOIN_GROUP, fee, joinerPublicKey, timestamp, reference, signature);
+ public JoinGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] joinerPublicKey, int groupId, byte[] inviteReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.JOIN_GROUP, timestamp, txGroupId, reference, joinerPublicKey, fee, signature);
this.joinerPublicKey = joinerPublicKey;
this.groupId = groupId;
@@ -47,8 +47,8 @@ public class JoinGroupTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public JoinGroupTransactionData(byte[] joinerPublicKey, int groupId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(joinerPublicKey, groupId, null, fee, timestamp, reference, signature);
+ public JoinGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] joinerPublicKey, int groupId, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, joinerPublicKey, groupId, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/LeaveGroupTransactionData.java b/src/main/java/org/qora/data/transaction/LeaveGroupTransactionData.java
index 7c2dfa5a..34b1c601 100644
--- a/src/main/java/org/qora/data/transaction/LeaveGroupTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/LeaveGroupTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class LeaveGroupTransactionData extends TransactionData {
@@ -34,7 +34,7 @@ public class LeaveGroupTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected LeaveGroupTransactionData() {
super(TransactionType.LEAVE_GROUP);
}
@@ -43,8 +43,8 @@ public class LeaveGroupTransactionData extends TransactionData {
this.creatorPublicKey = this.leaverPublicKey;
}
- public LeaveGroupTransactionData(byte[] leaverPublicKey, int groupId, byte[] memberReference, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.LEAVE_GROUP, fee, leaverPublicKey, timestamp, reference, signature);
+ public LeaveGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] leaverPublicKey, int groupId, byte[] memberReference, byte[] adminReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.LEAVE_GROUP, timestamp, txGroupId, reference, leaverPublicKey, fee, signature);
this.leaverPublicKey = leaverPublicKey;
this.groupId = groupId;
@@ -53,8 +53,8 @@ public class LeaveGroupTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public LeaveGroupTransactionData(byte[] leaverPublicKey, int groupId, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(leaverPublicKey, groupId, null, null, fee, timestamp, reference, signature);
+ public LeaveGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] leaverPublicKey, int groupId, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, leaverPublicKey, groupId, null, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/MessageTransactionData.java b/src/main/java/org/qora/data/transaction/MessageTransactionData.java
index 604ad1fe..a48a4584 100644
--- a/src/main/java/org/qora/data/transaction/MessageTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/MessageTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -10,14 +11,14 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class MessageTransactionData extends TransactionData {
// Properties
- private int version;
private byte[] senderPublicKey;
+ private int version;
private String recipient;
private Long assetId;
private BigDecimal amount;
@@ -27,16 +28,21 @@ public class MessageTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected MessageTransactionData() {
+ super(TransactionType.MESSAGE);
}
- public MessageTransactionData(int version, byte[] senderPublicKey, String recipient, Long assetId, BigDecimal amount, byte[] data, boolean isText,
- boolean isEncrypted, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.MESSAGE, fee, senderPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.senderPublicKey;
+ }
+
+ public MessageTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, int version, String recipient, Long assetId,
+ BigDecimal amount, byte[] data, boolean isText, boolean isEncrypted, BigDecimal fee, byte[] signature) {
+ super(TransactionType.MESSAGE, timestamp, txGroupId, reference, senderPublicKey, fee, signature);
- this.version = version;
this.senderPublicKey = senderPublicKey;
+ this.version = version;
this.recipient = recipient;
if (assetId != null)
@@ -50,21 +56,21 @@ public class MessageTransactionData extends TransactionData {
this.isEncrypted = isEncrypted;
}
- public MessageTransactionData(int version, byte[] senderPublicKey, String recipient, Long assetId, BigDecimal amount, byte[] data, boolean isText,
- boolean isEncrypted, BigDecimal fee, long timestamp, byte[] reference) {
- this(version, senderPublicKey, recipient, assetId, amount, data, isText, isEncrypted, fee, timestamp, reference, null);
+ public MessageTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, int version, String recipient, Long assetId,
+ BigDecimal amount, byte[] data, boolean isText, boolean isEncrypted, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, senderPublicKey, version, recipient, assetId, amount, data, isText, isEncrypted, fee, null);
}
// Getters/Setters
- public int getVersion() {
- return this.version;
- }
-
public byte[] getSenderPublicKey() {
return this.senderPublicKey;
}
+ public int getVersion() {
+ return this.version;
+ }
+
public String getRecipient() {
return this.recipient;
}
diff --git a/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java b/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java
index f63f52c7..d524eefc 100644
--- a/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/MultiPaymentTransactionData.java
@@ -3,15 +3,17 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
import java.util.List;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import org.qora.data.PaymentData;
import org.qora.transaction.Transaction;
+import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class MultiPaymentTransactionData extends TransactionData {
@@ -22,19 +24,24 @@ public class MultiPaymentTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected MultiPaymentTransactionData() {
+ super(TransactionType.MULTI_PAYMENT);
}
- public MultiPaymentTransactionData(byte[] senderPublicKey, List payments, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(Transaction.TransactionType.MULTI_PAYMENT, fee, senderPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.senderPublicKey;
+ }
+
+ public MultiPaymentTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, List payments, BigDecimal fee, byte[] signature) {
+ super(Transaction.TransactionType.MULTI_PAYMENT, timestamp, txGroupId, reference, senderPublicKey, fee, signature);
this.senderPublicKey = senderPublicKey;
this.payments = payments;
}
- public MultiPaymentTransactionData(byte[] senderPublicKey, List payments, BigDecimal fee, long timestamp, byte[] reference) {
- this(senderPublicKey, payments, fee, timestamp, reference, null);
+ public MultiPaymentTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, List payments, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, senderPublicKey, payments, fee, null);
}
// Getters/setters
diff --git a/src/main/java/org/qora/data/transaction/PaymentTransactionData.java b/src/main/java/org/qora/data/transaction/PaymentTransactionData.java
index c650ae82..cfd08a79 100644
--- a/src/main/java/org/qora/data/transaction/PaymentTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/PaymentTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@@ -10,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema( allOf = { TransactionData.class } )
public class PaymentTransactionData extends TransactionData {
@@ -29,22 +30,26 @@ public class PaymentTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected PaymentTransactionData() {
super(TransactionType.PAYMENT);
}
- public PaymentTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- super(TransactionType.PAYMENT, fee, senderPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.senderPublicKey;
+ }
+
+ public PaymentTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount,
+ BigDecimal fee, byte[] signature) {
+ super(TransactionType.PAYMENT, timestamp, txGroupId, reference, senderPublicKey, fee, signature);
this.senderPublicKey = senderPublicKey;
this.recipient = recipient;
this.amount = amount;
}
- public PaymentTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference) {
- this(senderPublicKey, recipient, amount, fee, timestamp, reference, null);
+ public PaymentTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, senderPublicKey, recipient, amount, fee, null);
}
// Getters/Setters
diff --git a/src/main/java/org/qora/data/transaction/RegisterNameTransactionData.java b/src/main/java/org/qora/data/transaction/RegisterNameTransactionData.java
index dcd4cd46..4582fdbc 100644
--- a/src/main/java/org/qora/data/transaction/RegisterNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/RegisterNameTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -9,7 +10,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class RegisterNameTransactionData extends TransactionData {
@@ -26,14 +27,18 @@ public class RegisterNameTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected RegisterNameTransactionData() {
super(TransactionType.REGISTER_NAME);
}
- public RegisterNameTransactionData(byte[] registrantPublicKey, String owner, String name, String data, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- super(TransactionType.REGISTER_NAME, fee, registrantPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.registrantPublicKey;
+ }
+
+ public RegisterNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] registrantPublicKey, String owner, String name, String data,
+ BigDecimal fee, byte[] signature) {
+ super(TransactionType.REGISTER_NAME, timestamp, txGroupId, reference, registrantPublicKey, fee, signature);
this.registrantPublicKey = registrantPublicKey;
this.owner = owner;
@@ -41,8 +46,8 @@ public class RegisterNameTransactionData extends TransactionData {
this.data = data;
}
- public RegisterNameTransactionData(byte[] registrantPublicKey, String owner, String name, String data, BigDecimal fee, long timestamp, byte[] reference) {
- this(registrantPublicKey, owner, name, data, fee, timestamp, reference, null);
+ public RegisterNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] registrantPublicKey, String owner, String name, String data, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, registrantPublicKey, owner, name, data, fee, null);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/RemoveGroupAdminTransactionData.java b/src/main/java/org/qora/data/transaction/RemoveGroupAdminTransactionData.java
index d254cf55..40639d9c 100644
--- a/src/main/java/org/qora/data/transaction/RemoveGroupAdminTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/RemoveGroupAdminTransactionData.java
@@ -11,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class RemoveGroupAdminTransactionData extends TransactionData {
@@ -31,7 +31,7 @@ public class RemoveGroupAdminTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected RemoveGroupAdminTransactionData() {
super(TransactionType.REMOVE_GROUP_ADMIN);
}
@@ -40,8 +40,8 @@ public class RemoveGroupAdminTransactionData extends TransactionData {
this.creatorPublicKey = this.ownerPublicKey;
}
- public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, int groupId, String admin, byte[] adminReference, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.REMOVE_GROUP_ADMIN, fee, ownerPublicKey, timestamp, reference, signature);
+ public RemoveGroupAdminTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, int groupId, String admin, byte[] adminReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.REMOVE_GROUP_ADMIN, timestamp, txGroupId, reference, ownerPublicKey, fee, signature);
this.ownerPublicKey = ownerPublicKey;
this.groupId = groupId;
@@ -50,8 +50,8 @@ public class RemoveGroupAdminTransactionData extends TransactionData {
}
/** Constructor typically used after deserialization */
- public RemoveGroupAdminTransactionData(byte[] ownerPublicKey, int groupId, String admin, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- this(ownerPublicKey, groupId, admin, null, fee, timestamp, reference, signature);
+ public RemoveGroupAdminTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, int groupId, String admin, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, ownerPublicKey, groupId, admin, null, fee, signature);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/SellNameTransactionData.java b/src/main/java/org/qora/data/transaction/SellNameTransactionData.java
index e7f9cef7..94f495a9 100644
--- a/src/main/java/org/qora/data/transaction/SellNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/SellNameTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
@@ -10,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class SellNameTransactionData extends TransactionData {
@@ -29,21 +30,25 @@ public class SellNameTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected SellNameTransactionData() {
super(TransactionType.SELL_NAME);
}
- public SellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference, byte[] signature) {
- super(TransactionType.SELL_NAME, fee, ownerPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.ownerPublicKey;
+ }
+
+ public SellNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, byte[] signature) {
+ super(TransactionType.SELL_NAME, timestamp, txGroupId, reference, ownerPublicKey, fee, signature);
this.ownerPublicKey = ownerPublicKey;
this.name = name;
this.amount = amount;
}
- public SellNameTransactionData(byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee, long timestamp, byte[] reference) {
- this(ownerPublicKey, name, amount, fee, timestamp, reference, null);
+ public SellNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String name, BigDecimal amount, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, ownerPublicKey, name, amount, fee, null);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/SetGroupTransactionData.java b/src/main/java/org/qora/data/transaction/SetGroupTransactionData.java
new file mode 100644
index 00000000..42fb5e2a
--- /dev/null
+++ b/src/main/java/org/qora/data/transaction/SetGroupTransactionData.java
@@ -0,0 +1,86 @@
+package org.qora.data.transaction;
+
+import java.math.BigDecimal;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlTransient;
+
+import org.qora.transaction.Transaction.TransactionType;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+
+// All properties to be converted to JSON via JAXB
+@XmlAccessorType(XmlAccessType.FIELD)
+@Schema(
+ allOf = {
+ TransactionData.class
+ }
+)
+public class SetGroupTransactionData extends TransactionData {
+
+ // Properties
+ @Schema(
+ description = "account's new default groupID",
+ example = "true"
+ )
+ private int defaultGroupId;
+ /** Reference to previous defaultGroupId, used during orphaning. */
+ // For internal use when orphaning
+ @XmlTransient
+ @Schema(
+ hidden = true
+ )
+ private Integer previousDefaultGroupId;
+
+ // Constructors
+
+ // For JAXB
+ protected SetGroupTransactionData() {
+ super(TransactionType.SET_GROUP);
+ }
+
+ public SetGroupTransactionData(long timestamp, int groupId, byte[] reference, byte[] creatorPublicKey, int defaultGroupId, Integer previousDefaultGroupId,
+ BigDecimal fee, byte[] signature) {
+ super(TransactionType.SET_GROUP, timestamp, groupId, reference, creatorPublicKey, fee, signature);
+
+ this.defaultGroupId = defaultGroupId;
+ this.previousDefaultGroupId = previousDefaultGroupId;
+ }
+
+ /** Constructor typically used after deserialization */
+ public SetGroupTransactionData(long timestamp, int groupId, byte[] reference, byte[] creatorPublicKey, int defaultGroupId, BigDecimal fee,
+ byte[] signature) {
+ this(timestamp, groupId, reference, creatorPublicKey, defaultGroupId, null, fee, signature);
+ }
+
+ // Getters / setters
+
+ public int getDefaultGroupId() {
+ return this.defaultGroupId;
+ }
+
+ public Integer getPreviousDefaultGroupId() {
+ return this.previousDefaultGroupId;
+ }
+
+ public void setPreviousDefaultGroupId(int previousDefaultGroupId) {
+ this.previousDefaultGroupId = previousDefaultGroupId;
+ }
+
+ // Re-expose to JAXB
+
+ @Override
+ @XmlElement
+ public byte[] getCreatorPublicKey() {
+ return super.getCreatorPublicKey();
+ }
+
+ @Override
+ @XmlElement
+ public void setCreatorPublicKey(byte[] creatorPublicKey) {
+ super.setCreatorPublicKey(creatorPublicKey);
+ }
+
+}
diff --git a/src/main/java/org/qora/data/transaction/TransactionData.java b/src/main/java/org/qora/data/transaction/TransactionData.java
index 37666ecf..4869ce38 100644
--- a/src/main/java/org/qora/data/transaction/TransactionData.java
+++ b/src/main/java/org/qora/data/transaction/TransactionData.java
@@ -10,9 +10,6 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.bind.annotation.XmlTransient;
-// XXX are this still needed? see below
-// import org.eclipse.persistence.oxm.annotations.XmlClassExtractor;
-// import org.qora.api.TransactionClassExtractor;
import org.qora.crypto.Crypto;
import org.qora.transaction.Transaction.TransactionType;
@@ -27,8 +24,6 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
* then chances are that class is missing a no-argument constructor!
*/
-// XXX is this still in use?
-// @XmlClassExtractor(TransactionClassExtractor.class)
@XmlSeeAlso({GenesisTransactionData.class, PaymentTransactionData.class, RegisterNameTransactionData.class, UpdateNameTransactionData.class,
SellNameTransactionData.class, CancelSellNameTransactionData.class, BuyNameTransactionData.class,
CreatePollTransactionData.class, VoteOnPollTransactionData.class, ArbitraryTransactionData.class,
@@ -39,9 +34,10 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode;
AddGroupAdminTransactionData.class, RemoveGroupAdminTransactionData.class,
GroupBanTransactionData.class, CancelGroupBanTransactionData.class,
GroupKickTransactionData.class, GroupInviteTransactionData.class,
- JoinGroupTransactionData.class, LeaveGroupTransactionData.class
+ JoinGroupTransactionData.class, LeaveGroupTransactionData.class,
+ GroupApprovalTransactionData.class, SetGroupTransactionData.class
})
-//All properties to be converted to JSON via JAX-RS
+//All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class TransactionData {
@@ -59,6 +55,8 @@ public abstract class TransactionData {
protected BigDecimal fee;
@Schema(accessMode = AccessMode.READ_ONLY, description = "signature for transaction's raw bytes, using sender's private key", example = "real_transaction_signature_in_base58")
protected byte[] signature;
+ @Schema(description = "groupID for this transaction")
+ protected int txGroupId;
// For JAX-RS use
@Schema(accessMode = AccessMode.READ_ONLY, hidden = true, description = "height of block containing transaction")
@@ -66,26 +64,27 @@ public abstract class TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected TransactionData() {
}
- // For JAX-RS
+ // For JAXB
protected TransactionData(TransactionType type) {
this.type = type;
}
- public TransactionData(TransactionType type, BigDecimal fee, byte[] creatorPublicKey, long timestamp, byte[] reference, byte[] signature) {
- this.fee = fee;
+ public TransactionData(TransactionType type, long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) {
this.type = type;
- this.creatorPublicKey = creatorPublicKey;
this.timestamp = timestamp;
+ this.txGroupId = txGroupId;
this.reference = reference;
+ this.creatorPublicKey = creatorPublicKey;
+ this.fee = fee;
this.signature = signature;
}
- public TransactionData(TransactionType type, BigDecimal fee, byte[] creatorPublicKey, long timestamp, byte[] reference) {
- this(type, fee, creatorPublicKey, timestamp, reference, null);
+ public TransactionData(TransactionType type, long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee) {
+ this(type, timestamp, txGroupId, reference, creatorPublicKey, fee, null);
}
// Getters/setters
@@ -94,18 +93,27 @@ public abstract class TransactionData {
return this.type;
}
- public byte[] getCreatorPublicKey() {
- return this.creatorPublicKey;
- }
-
public long getTimestamp() {
return this.timestamp;
}
+ public int getTxGroupId() {
+ return this.txGroupId;
+ }
+
public byte[] getReference() {
return this.reference;
}
+ public byte[] getCreatorPublicKey() {
+ return this.creatorPublicKey;
+ }
+
+ @XmlTransient
+ public void setCreatorPublicKey(byte[] creatorPublicKey) {
+ this.creatorPublicKey = creatorPublicKey;
+ }
+
public BigDecimal getFee() {
return this.fee;
}
@@ -125,11 +133,6 @@ public abstract class TransactionData {
return Crypto.toAddress(this.creatorPublicKey);
}
- @XmlTransient
- public void setCreatorPublicKey(byte[] creatorPublicKey) {
- this.creatorPublicKey = creatorPublicKey;
- }
-
@XmlTransient
public void setBlockHeight(int blockHeight) {
this.blockHeight = blockHeight;
diff --git a/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java b/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java
index 465b9895..9ee5b7b0 100644
--- a/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/TransferAssetTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -9,7 +10,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class TransferAssetTransactionData extends TransactionData {
@@ -22,13 +23,18 @@ public class TransferAssetTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected TransferAssetTransactionData() {
+ super(TransactionType.TRANSFER_ASSET);
}
- public TransferAssetTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, long assetId, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- super(TransactionType.TRANSFER_ASSET, fee, senderPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.senderPublicKey;
+ }
+
+ public TransferAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount,
+ long assetId, BigDecimal fee, byte[] signature) {
+ super(TransactionType.TRANSFER_ASSET, timestamp, txGroupId, reference, senderPublicKey, fee, signature);
this.senderPublicKey = senderPublicKey;
this.recipient = recipient;
@@ -36,9 +42,9 @@ public class TransferAssetTransactionData extends TransactionData {
this.assetId = assetId;
}
- public TransferAssetTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, long assetId, BigDecimal fee, long timestamp,
- byte[] reference) {
- this(senderPublicKey, recipient, amount, assetId, fee, timestamp, reference, null);
+ public TransferAssetTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] senderPublicKey, String recipient, BigDecimal amount,
+ long assetId, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, senderPublicKey, recipient, amount, assetId, fee, null);
}
// Getters/setters
diff --git a/src/main/java/org/qora/data/transaction/UpdateGroupTransactionData.java b/src/main/java/org/qora/data/transaction/UpdateGroupTransactionData.java
index 7ff6502b..d101702e 100644
--- a/src/main/java/org/qora/data/transaction/UpdateGroupTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/UpdateGroupTransactionData.java
@@ -7,35 +7,61 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
-@Schema(allOf = { TransactionData.class })
+@Schema(
+ allOf = {
+ TransactionData.class
+ }
+)
public class UpdateGroupTransactionData extends TransactionData {
// Properties
- @Schema(description = "owner's public key", example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP")
+ @Schema(
+ description = "owner's public key",
+ example = "2tiMr5LTpaWCgbRvkPK8TFd7k63DyHJMMFFsz9uBf1ZP"
+ )
private byte[] ownerPublicKey;
- @Schema(description = "new owner's address", example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v")
+ @Schema(
+ description = "new owner's address",
+ example = "QgV4s3xnzLhVBEJxcYui4u4q11yhUHsd9v"
+ )
private String newOwner;
- @Schema(description = "which group to update", example = "my-group")
+ @Schema(
+ description = "which group to update",
+ example = "my-group"
+ )
private int groupId;
- @Schema(description = "replacement group description", example = "my group for accounts I like")
+ @Schema(
+ description = "replacement group description",
+ example = "my group for accounts I like"
+ )
private String newDescription;
- @Schema(description = "new group join policy", example = "true")
+ @Schema(
+ description = "new group join policy",
+ example = "true"
+ )
private boolean newIsOpen;
+ @Schema(
+ description = "new group member transaction approval threshold"
+ )
+ private ApprovalThreshold newApprovalThreshold;
/** Reference to CREATE_GROUP or UPDATE_GROUP transaction, used to rebuild group during orphaning. */
// For internal use when orphaning
@XmlTransient
- @Schema(hidden = true)
+ @Schema(
+ hidden = true
+ )
private byte[] groupReference;
// Constructors
- // For JAX-RS
+ // For JAXB
protected UpdateGroupTransactionData() {
super(TransactionType.UPDATE_GROUP);
}
@@ -44,22 +70,23 @@ public class UpdateGroupTransactionData extends TransactionData {
this.creatorPublicKey = this.ownerPublicKey;
}
- public UpdateGroupTransactionData(byte[] ownerPublicKey, int groupId, String newOwner, String newDescription, boolean newIsOpen, byte[] groupReference, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- super(TransactionType.UPDATE_GROUP, fee, ownerPublicKey, timestamp, reference, signature);
+ public UpdateGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, int groupId,
+ String newOwner, String newDescription, boolean newIsOpen, ApprovalThreshold newApprovalThreshold, byte[] groupReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.UPDATE_GROUP, timestamp, txGroupId, reference, ownerPublicKey, fee, signature);
this.ownerPublicKey = ownerPublicKey;
this.newOwner = newOwner;
this.groupId = groupId;
this.newDescription = newDescription;
this.newIsOpen = newIsOpen;
+ this.newApprovalThreshold = newApprovalThreshold;
this.groupReference = groupReference;
}
/** Constructor typically used after deserialization */
- public UpdateGroupTransactionData(byte[] ownerPublicKey, int groupId, String newOwner, String newDescription, boolean newIsOpen, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- this(ownerPublicKey, groupId, newOwner, newDescription, newIsOpen, null, fee, timestamp, reference, signature);
+ public UpdateGroupTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, int groupId,
+ String newOwner, String newDescription, boolean newIsOpen, ApprovalThreshold newApprovalThreshold, BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, ownerPublicKey, groupId, newOwner, newDescription, newIsOpen, newApprovalThreshold, null, fee, signature);
}
// Getters / setters
@@ -84,6 +111,10 @@ public class UpdateGroupTransactionData extends TransactionData {
return this.newIsOpen;
}
+ public ApprovalThreshold getNewApprovalThreshold() {
+ return this.newApprovalThreshold;
+ }
+
public byte[] getGroupReference() {
return this.groupReference;
}
diff --git a/src/main/java/org/qora/data/transaction/UpdateNameTransactionData.java b/src/main/java/org/qora/data/transaction/UpdateNameTransactionData.java
index f4bb0e06..7abc601b 100644
--- a/src/main/java/org/qora/data/transaction/UpdateNameTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/UpdateNameTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlTransient;
@@ -10,7 +11,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class UpdateNameTransactionData extends TransactionData {
@@ -31,14 +32,18 @@ public class UpdateNameTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected UpdateNameTransactionData() {
super(TransactionType.UPDATE_NAME);
}
- public UpdateNameTransactionData(byte[] ownerPublicKey, String newOwner, String name, String newData, byte[] nameReference, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- super(TransactionType.UPDATE_NAME, fee, ownerPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.ownerPublicKey;
+ }
+
+ public UpdateNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String newOwner, String name, String newData,
+ byte[] nameReference, BigDecimal fee, byte[] signature) {
+ super(TransactionType.UPDATE_NAME, timestamp, txGroupId, reference, ownerPublicKey, fee, signature);
this.ownerPublicKey = ownerPublicKey;
this.newOwner = newOwner;
@@ -47,14 +52,14 @@ public class UpdateNameTransactionData extends TransactionData {
this.nameReference = nameReference;
}
- public UpdateNameTransactionData(byte[] ownerPublicKey, String newOwner, String name, String newData, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- this(ownerPublicKey, newOwner, name, newData, null, fee, timestamp, reference, signature);
+ public UpdateNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String newOwner, String name, String newData,
+ BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, ownerPublicKey, newOwner, name, newData, null, fee, signature);
}
- public UpdateNameTransactionData(byte[] ownerPublicKey, String newOwner, String name, String newData, byte[] nameReference, BigDecimal fee, long timestamp,
- byte[] reference) {
- this(ownerPublicKey, newOwner, name, newData, nameReference, fee, timestamp, reference, null);
+ public UpdateNameTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] ownerPublicKey, String newOwner, String name, String newData,
+ byte[] nameReference, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, ownerPublicKey, newOwner, name, newData, nameReference, fee, null);
}
// Getters / setters
diff --git a/src/main/java/org/qora/data/transaction/VoteOnPollTransactionData.java b/src/main/java/org/qora/data/transaction/VoteOnPollTransactionData.java
index 1c9f9075..124d7c07 100644
--- a/src/main/java/org/qora/data/transaction/VoteOnPollTransactionData.java
+++ b/src/main/java/org/qora/data/transaction/VoteOnPollTransactionData.java
@@ -2,6 +2,7 @@ package org.qora.data.transaction;
import java.math.BigDecimal;
+import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -9,7 +10,7 @@ import org.qora.transaction.Transaction.TransactionType;
import io.swagger.v3.oas.annotations.media.Schema;
-// All properties to be converted to JSON via JAX-RS
+// All properties to be converted to JSON via JAXB
@XmlAccessorType(XmlAccessType.FIELD)
@Schema(allOf = { TransactionData.class })
public class VoteOnPollTransactionData extends TransactionData {
@@ -22,13 +23,18 @@ public class VoteOnPollTransactionData extends TransactionData {
// Constructors
- // For JAX-RS
+ // For JAXB
protected VoteOnPollTransactionData() {
+ super(TransactionType.VOTE_ON_POLL);
}
- public VoteOnPollTransactionData(byte[] voterPublicKey, String pollName, int optionIndex, Integer previousOptionIndex, BigDecimal fee, long timestamp,
- byte[] reference, byte[] signature) {
- super(TransactionType.VOTE_ON_POLL, fee, voterPublicKey, timestamp, reference, signature);
+ public void afterUnmarshal(Unmarshaller u, Object parent) {
+ this.creatorPublicKey = this.voterPublicKey;
+ }
+
+ public VoteOnPollTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] voterPublicKey, String pollName, int optionIndex,
+ Integer previousOptionIndex, BigDecimal fee, byte[] signature) {
+ super(TransactionType.VOTE_ON_POLL, timestamp, txGroupId, reference, voterPublicKey, fee, signature);
this.voterPublicKey = voterPublicKey;
this.pollName = pollName;
@@ -36,13 +42,13 @@ public class VoteOnPollTransactionData extends TransactionData {
this.previousOptionIndex = previousOptionIndex;
}
- public VoteOnPollTransactionData(byte[] voterPublicKey, String pollName, int optionIndex, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
- this(voterPublicKey, pollName, optionIndex, null, fee, timestamp, reference, signature);
+ public VoteOnPollTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] voterPublicKey, String pollName, int optionIndex,
+ BigDecimal fee, byte[] signature) {
+ this(timestamp, txGroupId, reference, voterPublicKey, pollName, optionIndex, null, fee, signature);
}
- public VoteOnPollTransactionData(byte[] voterPublicKey, String pollName, int optionIndex, BigDecimal fee, long timestamp, byte[] reference) {
- this(voterPublicKey, pollName, optionIndex, null, fee, timestamp, reference, null);
+ public VoteOnPollTransactionData(long timestamp, int txGroupId, byte[] reference, byte[] voterPublicKey, String pollName, int optionIndex, BigDecimal fee) {
+ this(timestamp, txGroupId, reference, voterPublicKey, pollName, optionIndex, null, fee, null);
}
// Getters / setters
diff --git a/src/main/java/org/qora/group/Group.java b/src/main/java/org/qora/group/Group.java
index 7efdddd8..869b9daa 100644
--- a/src/main/java/org/qora/group/Group.java
+++ b/src/main/java/org/qora/group/Group.java
@@ -1,6 +1,10 @@
package org.qora.group;
+import static java.util.Arrays.stream;
+import static java.util.stream.Collectors.toMap;
+
import java.util.Arrays;
+import java.util.Map;
import org.qora.account.Account;
import org.qora.account.PublicKeyAccount;
@@ -28,12 +32,68 @@ import org.qora.repository.Repository;
public class Group {
+ /** Group-admin quora threshold for approving transactions */
+ public enum ApprovalThreshold {
+ // NOTE: value needs to fit into byte
+ NONE(0, false),
+ ONE(1, false),
+ PCT20(20, true),
+ PCT40(40, true),
+ PCT60(60, true),
+ PCT80(80, true),
+ PCT100(100, true);
+
+ public final int value;
+ public final boolean isPercentage;
+
+ private final static Map map = stream(ApprovalThreshold.values()).collect(toMap(threshold -> threshold.value, threshold -> threshold));
+
+ ApprovalThreshold(int value, boolean isPercentage) {
+ this.value = value;
+ this.isPercentage = isPercentage;
+ }
+
+ public static ApprovalThreshold valueOf(int value) {
+ return map.get(value);
+ }
+
+ private boolean meetsTheshold(int currentApprovals, int totalAdmins) {
+ if (!this.isPercentage)
+ return currentApprovals >= this.value;
+
+ return currentApprovals >= (totalAdmins * 100 / this.value);
+ }
+
+ /**
+ * Returns whether transaction need approval.
+ *
+ * @param repository
+ * @param txGroupId transaction's groupID
+ * @param signature transaction's signature
+ * @return true if approval still needed, false if transaction can be included in block
+ * @throws DataException
+ */
+ public boolean needsApproval(Repository repository, int txGroupId, byte[] signature) throws DataException {
+ // Fetch total number of admins in group
+ final int totalAdmins = repository.getGroupRepository().countGroupAdmins(txGroupId);
+
+ // Fetch total number of approvals for signature
+ // NOT simply number of GROUP_APPROVE transactions as some may be rejecting transaction, or changed opinions
+ final int currentApprovals = repository.getTransactionRepository().countTransactionApprovals(txGroupId, signature);
+
+ return !meetsTheshold(currentApprovals, totalAdmins);
+ }
+ }
+
// Properties
private Repository repository;
private GroupRepository groupRepository;
private GroupData groupData;
// Useful constants
+ public static final int NO_GROUP = -1;
+ public static final int DEFAULT_GROUP = 0;
+
public static final int MAX_NAME_SIZE = 32;
public static final int MAX_DESCRIPTION_SIZE = 128;
/** Max size of kick/ban reason */
@@ -53,7 +113,7 @@ public class Group {
this.groupData = new GroupData(createGroupTransactionData.getOwner(), createGroupTransactionData.getGroupName(),
createGroupTransactionData.getDescription(), createGroupTransactionData.getTimestamp(), createGroupTransactionData.getIsOpen(),
- createGroupTransactionData.getSignature());
+ createGroupTransactionData.getApprovalThreshold(), createGroupTransactionData.getSignature());
}
/**
@@ -253,6 +313,7 @@ public class Group {
this.groupData.setOwner(updateGroupTransactionData.getNewOwner());
this.groupData.setDescription(updateGroupTransactionData.getNewDescription());
this.groupData.setIsOpen(updateGroupTransactionData.getNewIsOpen());
+ this.groupData.setApprovalThreshold(updateGroupTransactionData.getNewApprovalThreshold());
this.groupData.setUpdated(updateGroupTransactionData.getTimestamp());
// Save updated group data
@@ -311,6 +372,7 @@ public class Group {
this.groupData.setOwner(previousCreateGroupTransactionData.getOwner());
this.groupData.setDescription(previousCreateGroupTransactionData.getDescription());
this.groupData.setIsOpen(previousCreateGroupTransactionData.getIsOpen());
+ this.groupData.setApprovalThreshold(previousCreateGroupTransactionData.getApprovalThreshold());
this.groupData.setUpdated(null);
break;
@@ -319,6 +381,7 @@ public class Group {
this.groupData.setOwner(previousUpdateGroupTransactionData.getNewOwner());
this.groupData.setDescription(previousUpdateGroupTransactionData.getNewDescription());
this.groupData.setIsOpen(previousUpdateGroupTransactionData.getNewIsOpen());
+ this.groupData.setApprovalThreshold(previousUpdateGroupTransactionData.getNewApprovalThreshold());
this.groupData.setUpdated(previousUpdateGroupTransactionData.getTimestamp());
break;
diff --git a/src/main/java/org/qora/repository/AccountRepository.java b/src/main/java/org/qora/repository/AccountRepository.java
index dde2738d..eac15023 100644
--- a/src/main/java/org/qora/repository/AccountRepository.java
+++ b/src/main/java/org/qora/repository/AccountRepository.java
@@ -9,11 +9,35 @@ public interface AccountRepository {
// General account
- public void create(AccountData accountData) throws DataException;
-
+ /** Returns all general information about account, e.g. public key, last reference, default group ID. */
public AccountData getAccount(String address) throws DataException;
- public void save(AccountData accountData) throws DataException;
+ /** Returns account's last reference or null if not set or account not found. */
+ public byte[] getLastReference(String address) throws DataException;
+
+ /** Returns account's default groupID or null if account not found. */
+ public Integer getDefaultGroupId(String address) throws DataException;
+
+ /**
+ * Ensures at least minimal account info in repository.
+ *
+ * Saves account address, and public key if present.
+ */
+ public void ensureAccount(AccountData accountData) throws DataException;
+
+ /**
+ * Saves account's last reference, and public key if present, in repository.
+ *
+ * Note: ignores other fields like default group ID.
+ */
+ public void setLastReference(AccountData accountData) throws DataException;
+
+ /**
+ * Saves account's default groupID, and public key if present, in repository.
+ *
+ * Note: ignores other fields like last reference.
+ */
+ public void setDefaultGroupId(AccountData accountData) throws DataException;
public void delete(String address) throws DataException;
diff --git a/src/main/java/org/qora/repository/TransactionRepository.java b/src/main/java/org/qora/repository/TransactionRepository.java
index 026340ac..74dbc383 100644
--- a/src/main/java/org/qora/repository/TransactionRepository.java
+++ b/src/main/java/org/qora/repository/TransactionRepository.java
@@ -3,6 +3,7 @@ package org.qora.repository;
import java.util.List;
import org.qora.api.resource.TransactionsResource.ConfirmationStatus;
+import org.qora.data.transaction.GroupApprovalTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.transaction.Transaction.TransactionType;
@@ -46,6 +47,20 @@ public interface TransactionRepository {
public List getAssetTransactions(int assetId, ConfirmationStatus confirmationStatus, Integer limit, Integer offset, Boolean reverse)
throws DataException;
+ /** Returns number of approvals for transaction with given signature. */
+ public int countTransactionApprovals(int txGroupId, byte[] signature) throws DataException;
+
+ /**
+ * Returns list of latest approval decisions per admin for given pending transaction signature.
+ *
+ * @param signature
+ * @param adminPublicKey
+ * restrict results to decision by this admin, pass null for all admins' results
+ * @return
+ * @throws DataException
+ */
+ public List getLatestApprovals(byte[] pendingSignature, byte[] adminPublicKey) throws DataException;
+
/**
* Returns whether transaction is confirmed or not.
*
diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java
index 9eaf6726..a432b0aa 100644
--- a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java
@@ -22,7 +22,48 @@ public class HSQLDBAccountRepository implements AccountRepository {
// General account
@Override
- public void create(AccountData accountData) throws DataException {
+ public AccountData getAccount(String address) throws DataException {
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT reference, public_key, default_group_id FROM Accounts WHERE account = ?", address)) {
+ if (resultSet == null)
+ return null;
+
+ byte[] reference = resultSet.getBytes(1);
+ byte[] publicKey = resultSet.getBytes(2);
+ int defaultGroupId = resultSet.getInt(3);
+
+ return new AccountData(address, reference, publicKey, defaultGroupId);
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch account info from repository", e);
+ }
+ }
+
+ @Override
+ public byte[] getLastReference(String address) throws DataException {
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT reference FROM Accounts WHERE account = ?", address)) {
+ if (resultSet == null)
+ return null;
+
+ return resultSet.getBytes(1);
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch account's last reference from repository", e);
+ }
+ }
+
+ @Override
+ public Integer getDefaultGroupId(String address) throws DataException {
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT default_group_id FROM Accounts WHERE account = ?", address)) {
+ if (resultSet == null)
+ return null;
+
+ // Column is NOT NULL so this should never implicitly convert to 0
+ return resultSet.getInt(1);
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch account's default groupID from repository", e);
+ }
+ }
+
+ @Override
+ public void ensureAccount(AccountData accountData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts");
saveHelper.bind("account", accountData.getAddress());
@@ -34,35 +75,41 @@ public class HSQLDBAccountRepository implements AccountRepository {
try {
saveHelper.execute(this.repository);
} catch (SQLException e) {
- throw new DataException("Unable to create account in repository", e);
+ throw new DataException("Unable to ensure minimal account in repository", e);
}
}
@Override
- public AccountData getAccount(String address) throws DataException {
- try (ResultSet resultSet = this.repository.checkedExecute("SELECT reference, public_key FROM Accounts WHERE account = ?", address)) {
- if (resultSet == null)
- return null;
-
- byte[] reference = resultSet.getBytes(1);
- byte[] publicKey = resultSet.getBytes(2);
-
- return new AccountData(address, reference, publicKey);
- } catch (SQLException e) {
- throw new DataException("Unable to fetch account info from repository", e);
- }
- }
-
- @Override
- public void save(AccountData accountData) throws DataException {
+ public void setLastReference(AccountData accountData) throws DataException {
HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts");
- saveHelper.bind("account", accountData.getAddress()).bind("reference", accountData.getReference()).bind("public_key", accountData.getPublicKey());
+ saveHelper.bind("account", accountData.getAddress()).bind("reference", accountData.getReference());
+
+ byte[] publicKey = accountData.getPublicKey();
+ if (publicKey != null)
+ saveHelper.bind("public_key", publicKey);
try {
saveHelper.execute(this.repository);
} catch (SQLException e) {
- throw new DataException("Unable to save account info into repository", e);
+ throw new DataException("Unable to save account's last reference into repository", e);
+ }
+ }
+
+ @Override
+ public void setDefaultGroupId(AccountData accountData) throws DataException {
+ HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts");
+
+ saveHelper.bind("account", accountData.getAddress()).bind("default_group_id", accountData.getDefaultGroupId());
+
+ byte[] publicKey = accountData.getPublicKey();
+ if (publicKey != null)
+ saveHelper.bind("public_key", publicKey);
+
+ try {
+ saveHelper.execute(this.repository);
+ } catch (SQLException e) {
+ throw new DataException("Unable to save account's default group ID into repository", e);
}
}
diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java
index 444abe83..8bd51b07 100644
--- a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java
+++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java
@@ -5,8 +5,13 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
public class HSQLDBDatabaseUpdates {
+ private static final Logger LOGGER = LogManager.getLogger(HSQLDBDatabaseUpdates.class);
+
/**
* Apply any incremental changes to database schema.
*
@@ -526,6 +531,33 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("ALTER TABLE PeersTEMP RENAME TO Peers");
break;
+ case 33:
+ // Add groupID to all transactions - groupID 0 is default, which means groupless/no-group
+ stmt.execute("ALTER TABLE Transactions ADD COLUMN tx_group_id GroupID NOT NULL DEFAULT 0");
+ stmt.execute("CREATE INDEX TransactionGroupIndex ON Transactions (tx_group_id)");
+
+ // Adding approval to group-based transactions
+ // Default approval threshold is 100% for existing groups but probably of no effect in production
+ stmt.execute("ALTER TABLE Groups ADD COLUMN approval_threshold TINYINT NOT NULL DEFAULT 100 BEFORE reference");
+ stmt.execute("ALTER TABLE CreateGroupTransactions ADD COLUMN approval_threshold TINYINT NOT NULL DEFAULT 100 BEFORE group_id");
+ stmt.execute("ALTER TABLE UpdateGroupTransactions ADD COLUMN new_approval_threshold TINYINT NOT NULL DEFAULT 100 BEFORE group_reference");
+
+ // Approval transactions themselves
+ // "pending_signature" contains signature of pending transaction requiring approval
+ // "prior_reference" contains signature of previous approval transaction for orphaning purposes
+ stmt.execute("CREATE TABLE GroupApprovalTransactions (signature Signature, admin QoraPublicKey NOT NULL, pending_signature Signature NOT NULL, approval BOOLEAN NOT NULL, "
+ + "prior_reference Signature, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
+
+ // Accounts have a default groupID to be used if transaction's txGroupId is 0
+ stmt.execute("ALTER TABLE Accounts add default_group_id GroupID NOT NULL DEFAULT 0");
+ break;
+
+ case 34:
+ // SET_GROUP transaction support
+ stmt.execute("CREATE TABLE SetGroupTransactions (signature Signature, default_group_id GroupID NOT NULL, previous_default_group_id GroupID, "
+ + "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
+ break;
+
default:
// nothing to do
return false;
@@ -533,6 +565,7 @@ public class HSQLDBDatabaseUpdates {
}
// database was updated
+ LOGGER.info(String.format("HSQLDB repository updated to version %d", databaseVersion + 1));
return true;
}
diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBGroupRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBGroupRepository.java
index e4795234..39ff765b 100644
--- a/src/main/java/org/qora/repository/hsqldb/HSQLDBGroupRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBGroupRepository.java
@@ -13,6 +13,7 @@ import org.qora.data.group.GroupData;
import org.qora.data.group.GroupInviteData;
import org.qora.data.group.GroupJoinRequestData;
import org.qora.data.group.GroupMemberData;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.repository.DataException;
import org.qora.repository.GroupRepository;
@@ -29,7 +30,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupData fromGroupId(int groupId) throws DataException {
try (ResultSet resultSet = this.repository
- .checkedExecute("SELECT group_name, owner, description, created, updated, reference, is_open FROM Groups WHERE group_id = ?", groupId)) {
+ .checkedExecute("SELECT group_name, owner, description, created, updated, reference, is_open, approval_threshold FROM Groups WHERE group_id = ?", groupId)) {
if (resultSet == null)
return null;
@@ -45,7 +46,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
- return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference);
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(8));
+
+ return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, reference);
} catch (SQLException e) {
throw new DataException("Unable to fetch group info from repository", e);
}
@@ -54,7 +57,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public GroupData fromGroupName(String groupName) throws DataException {
try (ResultSet resultSet = this.repository
- .checkedExecute("SELECT group_id, owner, description, created, updated, reference, is_open FROM Groups WHERE group_name = ?", groupName)) {
+ .checkedExecute("SELECT group_id, owner, description, created, updated, reference, is_open, approval_threshold FROM Groups WHERE group_name = ?", groupName)) {
if (resultSet == null)
return null;
@@ -70,7 +73,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
- return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference);
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(8));
+
+ return new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, reference);
} catch (SQLException e) {
throw new DataException("Unable to fetch group info from repository", e);
}
@@ -96,7 +101,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List getAllGroups(Integer limit, Integer offset, Boolean reverse) throws DataException {
- String sql = "SELECT group_id, owner, group_name, description, created, updated, reference, is_open FROM Groups ORDER BY group_name";
+ String sql = "SELECT group_id, owner, group_name, description, created, updated, reference, is_open, approval_threshold FROM Groups ORDER BY group_name";
if (reverse != null && reverse)
sql += " DESC";
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
@@ -121,7 +126,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(8);
- groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference));
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(9));
+
+ groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, reference));
} while (resultSet.next());
return groups;
@@ -132,7 +139,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List getGroupsByOwner(String owner, Integer limit, Integer offset, Boolean reverse) throws DataException {
- String sql = "SELECT group_id, group_name, description, created, updated, reference, is_open FROM Groups WHERE owner = ? ORDER BY group_name";
+ String sql = "SELECT group_id, group_name, description, created, updated, reference, is_open, approval_threshold FROM Groups WHERE owner = ? ORDER BY group_name";
if (reverse != null && reverse)
sql += " DESC";
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
@@ -156,7 +163,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(6);
boolean isOpen = resultSet.getBoolean(7);
- groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference));
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(8));
+
+ groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, reference));
} while (resultSet.next());
return groups;
@@ -167,7 +176,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
@Override
public List getGroupsWithMember(String member, Integer limit, Integer offset, Boolean reverse) throws DataException {
- String sql = "SELECT group_id, owner, group_name, description, created, updated, reference, is_open FROM Groups JOIN GroupMembers USING (group_id) WHERE address = ? ORDER BY group_name";
+ String sql = "SELECT group_id, owner, group_name, description, created, updated, reference, is_open, approval_threshold FROM Groups JOIN GroupMembers USING (group_id) WHERE address = ? ORDER BY group_name";
if (reverse != null && reverse)
sql += " DESC";
sql += HSQLDBRepository.limitOffsetSql(limit, offset);
@@ -192,7 +201,9 @@ public class HSQLDBGroupRepository implements GroupRepository {
byte[] reference = resultSet.getBytes(7);
boolean isOpen = resultSet.getBoolean(8);
- groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, reference));
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(9));
+
+ groups.add(new GroupData(groupId, owner, groupName, description, created, updated, isOpen, approvalThreshold, reference));
} while (resultSet.next());
return groups;
@@ -211,7 +222,7 @@ public class HSQLDBGroupRepository implements GroupRepository {
saveHelper.bind("group_id", groupData.getGroupId()).bind("owner", groupData.getOwner()).bind("group_name", groupData.getGroupName())
.bind("description", groupData.getDescription()).bind("created", new Timestamp(groupData.getCreated())).bind("updated", updatedTimestamp)
- .bind("reference", groupData.getReference()).bind("is_open", groupData.getIsOpen());
+ .bind("reference", groupData.getReference()).bind("is_open", groupData.getIsOpen()).bind("approval_threshold", groupData.getApprovalThreshold().value);
try {
saveHelper.execute(this.repository);
diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java
index efc6e1e1..455a53d6 100644
--- a/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBRepository.java
@@ -7,8 +7,8 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.ArrayDeque;
+import java.util.Deque;
import java.util.TimeZone;
import org.apache.logging.log4j.LogManager;
@@ -36,13 +36,13 @@ public class HSQLDBRepository implements Repository {
public static final TimeZone UTC = TimeZone.getTimeZone("UTC");
protected Connection connection;
- protected List savepoints;
+ protected Deque savepoints;
protected boolean debugState = false;
// NB: no visibility modifier so only callable from within same package
HSQLDBRepository(Connection connection) {
this.connection = connection;
- this.savepoints = new ArrayList<>();
+ this.savepoints = new ArrayDeque<>(3);
}
@Override
@@ -116,7 +116,7 @@ public class HSQLDBRepository implements Repository {
public void setSavepoint() throws DataException {
try {
Savepoint savepoint = this.connection.setSavepoint();
- this.savepoints.add(savepoint);
+ this.savepoints.push(savepoint);
} catch (SQLException e) {
throw new DataException("savepoint error", e);
}
@@ -127,8 +127,7 @@ public class HSQLDBRepository implements Repository {
if (this.savepoints.isEmpty())
throw new DataException("no savepoint to rollback");
- Savepoint savepoint = this.savepoints.get(0);
- this.savepoints.remove(0);
+ Savepoint savepoint = this.savepoints.pop();
try {
this.connection.rollback(savepoint);
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAddGroupAdminTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAddGroupAdminTransactionRepository.java
index 5388c184..11a7b511 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAddGroupAdminTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAddGroupAdminTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBAddGroupAdminTransactionRepository extends HSQLDBTransactionR
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, address FROM AddGroupAdminTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
@@ -24,7 +24,7 @@ public class HSQLDBAddGroupAdminTransactionRepository extends HSQLDBTransactionR
int groupId = resultSet.getInt(1);
String member = resultSet.getString(2);
- return new AddGroupAdminTransactionData(creatorPublicKey, groupId, member, fee, timestamp, reference, signature);
+ return new AddGroupAdminTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, member, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch add group admin transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java
index 8027a286..2148238a 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBArbitraryTransactionRepository.java
@@ -19,21 +19,20 @@ public class HSQLDBArbitraryTransactionRepository extends HSQLDBTransactionRepos
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
- try (ResultSet resultSet = this.repository.checkedExecute("SELECT sender, version, service, data_hash from ArbitraryTransactions WHERE signature = ?",
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT version, service, data_hash from ArbitraryTransactions WHERE signature = ?",
signature)) {
if (resultSet == null)
return null;
- byte[] senderPublicKey = resultSet.getBytes(1);
- int version = resultSet.getInt(2);
- int service = resultSet.getInt(3);
- byte[] dataHash = resultSet.getBytes(4);
+ int version = resultSet.getInt(1);
+ int service = resultSet.getInt(2);
+ byte[] dataHash = resultSet.getBytes(3);
List payments = this.getPaymentsFromSignature(signature);
- return new ArbitraryTransactionData(version, senderPublicKey, service, dataHash, DataType.DATA_HASH, payments, fee, timestamp, reference,
- signature);
+ return new ArbitraryTransactionData(timestamp, txGroupId, reference, creatorPublicKey, version, service, dataHash, DataType.DATA_HASH, payments,
+ fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch arbitrary transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAtTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAtTransactionRepository.java
index 8e8431ab..3b4f378f 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAtTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAtTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBAtTransactionRepository extends HSQLDBTransactionRepository {
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT AT_address, recipient, amount, asset_id, message FROM ATTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -37,7 +37,7 @@ public class HSQLDBAtTransactionRepository extends HSQLDBTransactionRepository {
if (resultSet.wasNull())
message = null;
- return new ATTransactionData(atAddress, recipient, amount, assetId, message, fee, timestamp, reference, signature);
+ return new ATTransactionData(timestamp, txGroupId, reference, atAddress, recipient, amount, assetId, message, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch AT transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java
index 62bb1c07..6c9f3f6b 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBBuyNameTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBBuyNameTransactionRepository extends HSQLDBTransactionReposit
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] buyerPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT name, amount, seller, name_reference FROM BuyNameTransactions WHERE signature = ?",
signature)) {
if (resultSet == null)
@@ -27,7 +27,7 @@ public class HSQLDBBuyNameTransactionRepository extends HSQLDBTransactionReposit
String seller = resultSet.getString(3);
byte[] nameReference = resultSet.getBytes(4);
- return new BuyNameTransactionData(buyerPublicKey, name, amount, seller, nameReference, fee, timestamp, reference, signature);
+ return new BuyNameTransactionData(timestamp, txGroupId, reference, creatorPublicKey, name, amount, seller, nameReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch buy name transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelAssetOrderTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelAssetOrderTransactionRepository.java
index 22a1c254..e035b936 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelAssetOrderTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelAssetOrderTransactionRepository.java
@@ -16,14 +16,14 @@ public class HSQLDBCancelAssetOrderTransactionRepository extends HSQLDBTransacti
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT asset_order_id FROM CancelAssetOrderTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
byte[] assetOrderId = resultSet.getBytes(1);
- return new CancelAssetOrderTransactionData(creatorPublicKey, assetOrderId, fee, timestamp, reference, signature);
+ return new CancelAssetOrderTransactionData(timestamp, txGroupId, reference, creatorPublicKey, assetOrderId, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch cancel order transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupBanTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupBanTransactionRepository.java
index 605eab7b..6f16fadb 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupBanTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupBanTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBCancelGroupBanTransactionRepository extends HSQLDBTransaction
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, address, ban_reference FROM CancelGroupBanTransactions WHERE signature = ?",
signature)) {
if (resultSet == null)
@@ -26,7 +26,7 @@ public class HSQLDBCancelGroupBanTransactionRepository extends HSQLDBTransaction
String member = resultSet.getString(2);
byte[] banReference = resultSet.getBytes(3);
- return new CancelGroupBanTransactionData(creatorPublicKey, groupId, member, banReference, fee, timestamp, reference, signature);
+ return new CancelGroupBanTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, member, banReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch group unban transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupInviteTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupInviteTransactionRepository.java
index a35a58c5..382c4a4e 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupInviteTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelGroupInviteTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBCancelGroupInviteTransactionRepository extends HSQLDBTransact
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_id, invitee, invite_reference FROM CancelGroupInviteTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -26,7 +26,7 @@ public class HSQLDBCancelGroupInviteTransactionRepository extends HSQLDBTransact
String invitee = resultSet.getString(2);
byte[] inviteReference = resultSet.getBytes(3);
- return new CancelGroupInviteTransactionData(creatorPublicKey, groupId, invitee, inviteReference, fee, timestamp, reference, signature);
+ return new CancelGroupInviteTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, invitee, inviteReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch cancel group invite transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java
index 3fbf9008..6ff43a01 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCancelSellNameTransactionRepository.java
@@ -16,14 +16,14 @@ public class HSQLDBCancelSellNameTransactionRepository extends HSQLDBTransaction
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] ownerPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT name FROM CancelSellNameTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
String name = resultSet.getString(1);
- return new CancelSellNameTransactionData(ownerPublicKey, name, fee, timestamp, reference, signature);
+ return new CancelSellNameTransactionData(timestamp, txGroupId, reference, creatorPublicKey, name, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch cancel sell name transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateAssetOrderTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateAssetOrderTransactionRepository.java
index 0ccbf2a7..1dc663a8 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateAssetOrderTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateAssetOrderTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBCreateAssetOrderTransactionRepository extends HSQLDBTransacti
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT have_asset_id, amount, want_asset_id, price FROM CreateAssetOrderTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -27,7 +27,7 @@ public class HSQLDBCreateAssetOrderTransactionRepository extends HSQLDBTransacti
long wantAssetId = resultSet.getLong(3);
BigDecimal price = resultSet.getBigDecimal(4);
- return new CreateAssetOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature);
+ return new CreateAssetOrderTransactionData(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch create order transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateGroupTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateGroupTransactionRepository.java
index 1d8b3c83..098d4dd1 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateGroupTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreateGroupTransactionRepository.java
@@ -6,6 +6,7 @@ import java.sql.SQLException;
import org.qora.data.transaction.CreateGroupTransactionData;
import org.qora.data.transaction.TransactionData;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.repository.DataException;
import org.qora.repository.hsqldb.HSQLDBRepository;
import org.qora.repository.hsqldb.HSQLDBSaver;
@@ -16,9 +17,9 @@ public class HSQLDBCreateGroupTransactionRepository extends HSQLDBTransactionRep
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
- .checkedExecute("SELECT owner, group_name, description, is_open, group_id FROM CreateGroupTransactions WHERE signature = ?", signature)) {
+ .checkedExecute("SELECT owner, group_name, description, is_open, approval_threshold, group_id FROM CreateGroupTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
@@ -27,11 +28,14 @@ public class HSQLDBCreateGroupTransactionRepository extends HSQLDBTransactionRep
String description = resultSet.getString(3);
boolean isOpen = resultSet.getBoolean(4);
- Integer groupId = resultSet.getInt(5);
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(5));
+
+ Integer groupId = resultSet.getInt(6);
if (resultSet.wasNull())
groupId = null;
- return new CreateGroupTransactionData(creatorPublicKey, owner, groupName, description, isOpen, groupId, fee, timestamp, reference, signature);
+ return new CreateGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, owner, groupName, description, isOpen, approvalThreshold,
+ groupId, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch create group transaction from repository", e);
}
@@ -46,6 +50,7 @@ public class HSQLDBCreateGroupTransactionRepository extends HSQLDBTransactionRep
saveHelper.bind("signature", createGroupTransactionData.getSignature()).bind("creator", createGroupTransactionData.getCreatorPublicKey())
.bind("owner", createGroupTransactionData.getOwner()).bind("group_name", createGroupTransactionData.getGroupName())
.bind("description", createGroupTransactionData.getDescription()).bind("is_open", createGroupTransactionData.getIsOpen())
+ .bind("approval_threshold", createGroupTransactionData.getApprovalThreshold().value)
.bind("group_id", createGroupTransactionData.getGroupId());
try {
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java
index 838a1801..50c63547 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBCreatePollTransactionRepository.java
@@ -19,7 +19,7 @@ public class HSQLDBCreatePollTransactionRepository extends HSQLDBTransactionRepo
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT owner, poll_name, description FROM CreatePollTransactions WHERE signature = ?",
signature)) {
if (resultSet == null)
@@ -43,7 +43,7 @@ public class HSQLDBCreatePollTransactionRepository extends HSQLDBTransactionRepo
pollOptions.add(new PollOptionData(optionName));
} while (optionsResultSet.next());
- return new CreatePollTransactionData(creatorPublicKey, owner, pollName, description, pollOptions, fee, timestamp, reference, signature);
+ return new CreatePollTransactionData(timestamp, txGroupId, reference, creatorPublicKey, owner, pollName, description, pollOptions, fee, signature);
}
} catch (SQLException e) {
throw new DataException("Unable to fetch create poll transaction from repository", e);
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 bcc4784e..fb011631 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBDeployAtTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBDeployAtTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBDeployAtTransactionRepository extends HSQLDBTransactionReposi
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT AT_name, description, AT_type, AT_tags, creation_bytes, amount, asset_id, AT_address FROM DeployATTransactions WHERE signature = ?",
signature)) {
@@ -25,19 +25,19 @@ public class HSQLDBDeployAtTransactionRepository extends HSQLDBTransactionReposi
String name = resultSet.getString(1);
String description = resultSet.getString(2);
- String ATType = resultSet.getString(3);
+ String atType = resultSet.getString(3);
String tags = resultSet.getString(4);
byte[] creationBytes = resultSet.getBytes(5);
BigDecimal amount = resultSet.getBigDecimal(6).setScale(8);
long assetId = resultSet.getLong(7);
// Special null-checking for AT address
- String ATAddress = resultSet.getString(8);
+ String atAddress = resultSet.getString(8);
if (resultSet.wasNull())
- ATAddress = null;
+ atAddress = null;
- return new DeployAtTransactionData(ATAddress, creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId, fee, timestamp,
- reference, signature);
+ return new DeployAtTransactionData(timestamp, txGroupId, reference, creatorPublicKey, atAddress, name, description, atType, tags, creationBytes, amount,
+ assetId, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch deploy AT transaction from repository", e);
}
@@ -51,9 +51,9 @@ public class HSQLDBDeployAtTransactionRepository extends HSQLDBTransactionReposi
saveHelper.bind("signature", deployATTransactionData.getSignature()).bind("creator", deployATTransactionData.getCreatorPublicKey())
.bind("AT_name", deployATTransactionData.getName()).bind("description", deployATTransactionData.getDescription())
- .bind("AT_type", deployATTransactionData.getATType()).bind("AT_tags", deployATTransactionData.getTags())
+ .bind("AT_type", deployATTransactionData.getAtType()).bind("AT_tags", deployATTransactionData.getTags())
.bind("creation_bytes", deployATTransactionData.getCreationBytes()).bind("amount", deployATTransactionData.getAmount())
- .bind("asset_id", deployATTransactionData.getAssetId()).bind("AT_address", deployATTransactionData.getATAddress());
+ .bind("asset_id", deployATTransactionData.getAssetId()).bind("AT_address", deployATTransactionData.getAtAddress());
try {
saveHelper.execute(this.repository);
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java
index c8b11183..130af39b 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGenesisTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBGenesisTransactionRepository extends HSQLDBTransactionReposit
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT recipient, amount, asset_id FROM GenesisTransactions WHERE signature = ?",
signature)) {
if (resultSet == null)
@@ -26,7 +26,7 @@ public class HSQLDBGenesisTransactionRepository extends HSQLDBTransactionReposit
BigDecimal amount = resultSet.getBigDecimal(2).setScale(8);
long assetId = resultSet.getLong(3);
- return new GenesisTransactionData(recipient, amount, assetId, timestamp, signature);
+ return new GenesisTransactionData(timestamp, recipient, amount, assetId, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch genesis transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupApprovalTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupApprovalTransactionRepository.java
new file mode 100644
index 00000000..351efac1
--- /dev/null
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupApprovalTransactionRepository.java
@@ -0,0 +1,53 @@
+package org.qora.repository.hsqldb.transaction;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.qora.data.transaction.GroupApprovalTransactionData;
+import org.qora.data.transaction.TransactionData;
+import org.qora.repository.DataException;
+import org.qora.repository.hsqldb.HSQLDBRepository;
+import org.qora.repository.hsqldb.HSQLDBSaver;
+
+public class HSQLDBGroupApprovalTransactionRepository extends HSQLDBTransactionRepository {
+
+ public HSQLDBGroupApprovalTransactionRepository(HSQLDBRepository repository) {
+ this.repository = repository;
+ }
+
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
+ try (ResultSet resultSet = this.repository
+ .checkedExecute("SELECT pending_signature, approval, prior_reference FROM GroupApprovalTransactions WHERE signature = ?", signature)) {
+ if (resultSet == null)
+ return null;
+
+ byte[] pendingSignature = resultSet.getBytes(1);
+ boolean approval = resultSet.getBoolean(2);
+ byte[] priorReference = resultSet.getBytes(3);
+
+ return new GroupApprovalTransactionData(timestamp, txGroupId, reference, creatorPublicKey, pendingSignature, approval, priorReference, fee,
+ signature);
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch group approval transaction from repository", e);
+ }
+ }
+
+ @Override
+ public void save(TransactionData transactionData) throws DataException {
+ GroupApprovalTransactionData groupApprovalTransactionData = (GroupApprovalTransactionData) transactionData;
+
+ HSQLDBSaver saveHelper = new HSQLDBSaver("GroupApprovalTransactions");
+
+ saveHelper.bind("signature", groupApprovalTransactionData.getSignature()).bind("admin", groupApprovalTransactionData.getAdminPublicKey())
+ .bind("pending_signature", groupApprovalTransactionData.getPendingSignature()).bind("approval", groupApprovalTransactionData.getApproval())
+ .bind("prior_reference", groupApprovalTransactionData.getPriorReference());
+
+ try {
+ saveHelper.execute(this.repository);
+ } catch (SQLException e) {
+ throw new DataException("Unable to save group approval transaction into repository", e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupBanTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupBanTransactionRepository.java
index fe3806cf..37825ee2 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupBanTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupBanTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBGroupBanTransactionRepository extends HSQLDBTransactionReposi
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT group_id, address, reason, time_to_live, member_reference, admin_reference, join_invite_reference FROM GroupBanTransactions WHERE signature = ?",
signature)) {
@@ -31,8 +31,8 @@ public class HSQLDBGroupBanTransactionRepository extends HSQLDBTransactionReposi
byte[] adminReference = resultSet.getBytes(6);
byte[] joinInviteReference = resultSet.getBytes(7);
- return new GroupBanTransactionData(creatorPublicKey, groupId, offender, reason, timeToLive, memberReference, adminReference, joinInviteReference,
- fee, timestamp, reference, signature);
+ return new GroupBanTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, offender, reason, timeToLive,
+ memberReference, adminReference, joinInviteReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch group ban transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupInviteTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupInviteTransactionRepository.java
index d1fbe37c..b2a3a9a4 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupInviteTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupInviteTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBGroupInviteTransactionRepository extends HSQLDBTransactionRep
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_id, invitee, time_to_live, join_reference FROM GroupInviteTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -27,7 +27,7 @@ public class HSQLDBGroupInviteTransactionRepository extends HSQLDBTransactionRep
int timeToLive = resultSet.getInt(3);
byte[] joinReference = resultSet.getBytes(4);
- return new GroupInviteTransactionData(creatorPublicKey, groupId, invitee, timeToLive, joinReference, fee, timestamp, reference, signature);
+ return new GroupInviteTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, invitee, timeToLive, joinReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch group invite transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupKickTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupKickTransactionRepository.java
index 4b9c32e3..dbe194de 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupKickTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBGroupKickTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBGroupKickTransactionRepository extends HSQLDBTransactionRepos
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
"SELECT group_id, address, reason, member_reference, admin_reference, join_reference FROM GroupKickTransactions WHERE signature = ?",
signature)) {
@@ -30,8 +30,8 @@ public class HSQLDBGroupKickTransactionRepository extends HSQLDBTransactionRepos
byte[] adminReference = resultSet.getBytes(5);
byte[] joinReference = resultSet.getBytes(6);
- return new GroupKickTransactionData(creatorPublicKey, groupId, member, reason, memberReference, adminReference, joinReference, fee, timestamp,
- reference, signature);
+ return new GroupKickTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, member, reason, memberReference, adminReference,
+ joinReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch group kick transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java
index 270c2d6d..cd5ffb8d 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBIssueAssetTransactionRepository.java
@@ -16,26 +16,25 @@ public class HSQLDBIssueAssetTransactionRepository extends HSQLDBTransactionRepo
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
- "SELECT issuer, owner, asset_name, description, quantity, is_divisible, asset_id FROM IssueAssetTransactions WHERE signature = ?", signature)) {
+ "SELECT owner, asset_name, description, quantity, is_divisible, asset_id FROM IssueAssetTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
- byte[] issuerPublicKey = resultSet.getBytes(1);
- String owner = resultSet.getString(2);
- String assetName = resultSet.getString(3);
- String description = resultSet.getString(4);
- long quantity = resultSet.getLong(5);
- boolean isDivisible = resultSet.getBoolean(6);
+ String owner = resultSet.getString(1);
+ String assetName = resultSet.getString(2);
+ String description = resultSet.getString(3);
+ long quantity = resultSet.getLong(4);
+ boolean isDivisible = resultSet.getBoolean(5);
// Special null-checking for asset ID
- Long assetId = resultSet.getLong(7);
+ Long assetId = resultSet.getLong(6);
if (resultSet.wasNull())
assetId = null;
- return new IssueAssetTransactionData(assetId, issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference,
- signature);
+ return new IssueAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, assetId, owner, assetName, description, quantity, isDivisible,
+ fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch issue asset transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBJoinGroupTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBJoinGroupTransactionRepository.java
index b54bef75..98dce60d 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBJoinGroupTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBJoinGroupTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBJoinGroupTransactionRepository extends HSQLDBTransactionRepos
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT group_id, invite_reference FROM JoinGroupTransactions WHERE signature = ?",
signature)) {
if (resultSet == null)
@@ -25,7 +25,7 @@ public class HSQLDBJoinGroupTransactionRepository extends HSQLDBTransactionRepos
int groupId = resultSet.getInt(1);
byte[] inviteReference = resultSet.getBytes(2);
- return new JoinGroupTransactionData(creatorPublicKey, groupId, inviteReference, fee, timestamp, reference, signature);
+ return new JoinGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, inviteReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch join group transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBLeaveGroupTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBLeaveGroupTransactionRepository.java
index 872d119e..470fb6a0 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBLeaveGroupTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBLeaveGroupTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBLeaveGroupTransactionRepository extends HSQLDBTransactionRepo
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_id, member_reference, admin_reference FROM LeaveGroupTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -26,7 +26,7 @@ public class HSQLDBLeaveGroupTransactionRepository extends HSQLDBTransactionRepo
byte[] memberReference = resultSet.getBytes(2);
byte[] adminReference = resultSet.getBytes(3);
- return new LeaveGroupTransactionData(creatorPublicKey, groupId, memberReference, adminReference, fee, timestamp, reference, signature);
+ return new LeaveGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, memberReference, adminReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch leave group transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java
index edad7e46..af71837b 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMessageTransactionRepository.java
@@ -16,28 +16,27 @@ public class HSQLDBMessageTransactionRepository extends HSQLDBTransactionReposit
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
- "SELECT version, sender, recipient, is_text, is_encrypted, amount, asset_id, data FROM MessageTransactions WHERE signature = ?", signature)) {
+ "SELECT version, recipient, is_text, is_encrypted, amount, asset_id, data FROM MessageTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
int version = resultSet.getInt(1);
- byte[] senderPublicKey = resultSet.getBytes(2);
- String recipient = resultSet.getString(3);
- boolean isText = resultSet.getBoolean(4);
- boolean isEncrypted = resultSet.getBoolean(5);
- BigDecimal amount = resultSet.getBigDecimal(6);
+ String recipient = resultSet.getString(2);
+ boolean isText = resultSet.getBoolean(3);
+ boolean isEncrypted = resultSet.getBoolean(4);
+ BigDecimal amount = resultSet.getBigDecimal(5);
// Special null-checking for asset ID
- Long assetId = resultSet.getLong(7);
+ Long assetId = resultSet.getLong(6);
if (resultSet.wasNull())
assetId = null;
- byte[] data = resultSet.getBytes(8);
+ byte[] data = resultSet.getBytes(7);
- return new MessageTransactionData(version, senderPublicKey, recipient, assetId, amount, data, isText, isEncrypted, fee, timestamp, reference,
- signature);
+ return new MessageTransactionData(timestamp, txGroupId, reference, creatorPublicKey, version, recipient, assetId, amount, data, isText, isEncrypted,
+ fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch message transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java
index 20b4a38d..b7e62f8f 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBMultiPaymentTransactionRepository.java
@@ -18,16 +18,14 @@ public class HSQLDBMultiPaymentTransactionRepository extends HSQLDBTransactionRe
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
- try (ResultSet resultSet = this.repository.checkedExecute("SELECT sender from MultiPaymentTransactions WHERE signature = ?", signature)) {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT TRUE from MultiPaymentTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
- byte[] senderPublicKey = resultSet.getBytes(1);
-
List payments = this.getPaymentsFromSignature(signature);
- return new MultiPaymentTransactionData(senderPublicKey, payments, fee, timestamp, reference, signature);
+ return new MultiPaymentTransactionData(timestamp, txGroupId, reference, creatorPublicKey, payments, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch multi-payment transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java
index 026d63cf..6307f833 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBPaymentTransactionRepository.java
@@ -16,16 +16,15 @@ public class HSQLDBPaymentTransactionRepository extends HSQLDBTransactionReposit
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
- try (ResultSet resultSet = this.repository.checkedExecute("SELECT sender, recipient, amount FROM PaymentTransactions WHERE signature = ?", signature)) {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT recipient, amount FROM PaymentTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
- byte[] senderPublicKey = resultSet.getBytes(1);
- String recipient = resultSet.getString(2);
- BigDecimal amount = resultSet.getBigDecimal(3);
+ String recipient = resultSet.getString(1);
+ BigDecimal amount = resultSet.getBigDecimal(2);
- return new PaymentTransactionData(senderPublicKey, recipient, amount, fee, timestamp, reference, signature);
+ return new PaymentTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch payment transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java
index fb6813be..261aa1ca 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRegisterNameTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBRegisterNameTransactionRepository extends HSQLDBTransactionRe
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] registrantPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT owner, name, data FROM RegisterNameTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
@@ -25,7 +25,7 @@ public class HSQLDBRegisterNameTransactionRepository extends HSQLDBTransactionRe
String name = resultSet.getString(2);
String data = resultSet.getString(3);
- return new RegisterNameTransactionData(registrantPublicKey, owner, name, data, fee, timestamp, reference, signature);
+ return new RegisterNameTransactionData(timestamp, txGroupId, reference, creatorPublicKey, owner, name, data, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch register name transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRemoveGroupAdminTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRemoveGroupAdminTransactionRepository.java
index ca69996b..a01d6e38 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRemoveGroupAdminTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBRemoveGroupAdminTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBRemoveGroupAdminTransactionRepository extends HSQLDBTransacti
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT group_id, admin, admin_reference FROM RemoveGroupAdminTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -26,7 +26,7 @@ public class HSQLDBRemoveGroupAdminTransactionRepository extends HSQLDBTransacti
String admin = resultSet.getString(2);
byte[] adminReference = resultSet.getBytes(3);
- return new RemoveGroupAdminTransactionData(creatorPublicKey, groupId, admin, adminReference, fee, timestamp, reference, signature);
+ return new RemoveGroupAdminTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, admin, adminReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch remove group admin transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java
index e76ed907..f02c6f67 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSellNameTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBSellNameTransactionRepository extends HSQLDBTransactionReposi
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] ownerPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT name, amount FROM SellNameTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
@@ -24,7 +24,7 @@ public class HSQLDBSellNameTransactionRepository extends HSQLDBTransactionReposi
String name = resultSet.getString(1);
BigDecimal amount = resultSet.getBigDecimal(2);
- return new SellNameTransactionData(ownerPublicKey, name, amount, fee, timestamp, reference, signature);
+ return new SellNameTransactionData(timestamp, txGroupId, reference, creatorPublicKey, name, amount, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch sell name transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSetGroupTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSetGroupTransactionRepository.java
new file mode 100644
index 00000000..92dba478
--- /dev/null
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBSetGroupTransactionRepository.java
@@ -0,0 +1,52 @@
+package org.qora.repository.hsqldb.transaction;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import org.qora.data.transaction.SetGroupTransactionData;
+import org.qora.data.transaction.TransactionData;
+import org.qora.repository.DataException;
+import org.qora.repository.hsqldb.HSQLDBRepository;
+import org.qora.repository.hsqldb.HSQLDBSaver;
+
+public class HSQLDBSetGroupTransactionRepository extends HSQLDBTransactionRepository {
+
+ public HSQLDBSetGroupTransactionRepository(HSQLDBRepository repository) {
+ this.repository = repository;
+ }
+
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
+ try (ResultSet resultSet = this.repository
+ .checkedExecute("SELECT default_group_id, previous_default_group_id FROM SetGroupTransactions WHERE signature = ?", signature)) {
+ if (resultSet == null)
+ return null;
+
+ int defaultGroupId = resultSet.getInt(1);
+ Integer previousDefaultGroupId = resultSet.getInt(2);
+ if (resultSet.wasNull())
+ previousDefaultGroupId = null;
+
+ return new SetGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, defaultGroupId, previousDefaultGroupId, fee, signature);
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch set group transaction from repository", e);
+ }
+ }
+
+ @Override
+ public void save(TransactionData transactionData) throws DataException {
+ SetGroupTransactionData setGroupTransactionData = (SetGroupTransactionData) transactionData;
+
+ HSQLDBSaver saveHelper = new HSQLDBSaver("SetGroupTransactions");
+
+ saveHelper.bind("signature", setGroupTransactionData.getSignature()).bind("default_group_id", setGroupTransactionData.getDefaultGroupId())
+ .bind("previous_default_group_id", setGroupTransactionData.getPreviousDefaultGroupId());
+
+ try {
+ saveHelper.execute(this.repository);
+ } catch (SQLException e) {
+ throw new DataException("Unable to save set group transaction into repository", e);
+ }
+ }
+
+}
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 e61ea4e2..84a1af77 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
@@ -17,6 +17,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.qora.api.resource.TransactionsResource.ConfirmationStatus;
import org.qora.data.PaymentData;
+import org.qora.data.transaction.GroupApprovalTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.repository.DataException;
import org.qora.repository.TransactionRepository;
@@ -60,8 +61,8 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
}
try {
- subclassInfo.fromBaseMethod = subclassInfo.clazz.getDeclaredMethod("fromBase", byte[].class, byte[].class, byte[].class, long.class,
- BigDecimal.class);
+ // params: long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature
+ subclassInfo.fromBaseMethod = subclassInfo.clazz.getDeclaredMethod("fromBase", long.class, int.class, byte[].class, byte[].class, BigDecimal.class, byte[].class);
} catch (IllegalArgumentException | SecurityException | NoSuchMethodException e) {
LOGGER.debug(String.format("HSQLDBTransactionRepository subclass's \"fromBase\" method not found for transaction type \"%s\"", txType.name()));
}
@@ -110,7 +111,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
@Override
public TransactionData fromSignature(byte[] signature) throws DataException {
- try (ResultSet resultSet = this.repository.checkedExecute("SELECT type, reference, creator, creation, fee FROM Transactions WHERE signature = ?",
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT type, reference, creator, creation, fee, tx_group_id FROM Transactions WHERE signature = ?",
signature)) {
if (resultSet == null)
return null;
@@ -120,8 +121,9 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
byte[] creatorPublicKey = resultSet.getBytes(3);
long timestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
BigDecimal fee = resultSet.getBigDecimal(5).setScale(8);
+ int txGroupId = resultSet.getInt(6);
- TransactionData transactionData = this.fromBase(type, signature, reference, creatorPublicKey, timestamp, fee);
+ TransactionData transactionData = this.fromBase(type, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
return maybeIncludeBlockHeight(transactionData);
} catch (SQLException e) {
throw new DataException("Unable to fetch transaction from repository", e);
@@ -130,7 +132,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
@Override
public TransactionData fromReference(byte[] reference) throws DataException {
- try (ResultSet resultSet = this.repository.checkedExecute("SELECT type, signature, creator, creation, fee FROM Transactions WHERE reference = ?",
+ try (ResultSet resultSet = this.repository.checkedExecute("SELECT type, signature, creator, creation, fee, tx_group_id FROM Transactions WHERE reference = ?",
reference)) {
if (resultSet == null)
return null;
@@ -140,8 +142,9 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
byte[] creatorPublicKey = resultSet.getBytes(3);
long timestamp = resultSet.getTimestamp(4, Calendar.getInstance(HSQLDBRepository.UTC)).getTime();
BigDecimal fee = resultSet.getBigDecimal(5).setScale(8);
+ int txGroupId = resultSet.getInt(6);
- TransactionData transactionData = this.fromBase(type, signature, reference, creatorPublicKey, timestamp, fee);
+ TransactionData transactionData = this.fromBase(type, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
return maybeIncludeBlockHeight(transactionData);
} catch (SQLException e) {
throw new DataException("Unable to fetch transaction from repository", e);
@@ -172,14 +175,15 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
}
}
- private TransactionData fromBase(TransactionType type, byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee)
+ private TransactionData fromBase(TransactionType type, long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature)
throws DataException {
HSQLDBTransactionRepository txRepository = repositoryByTxType[type.value];
if (txRepository == null)
throw new DataException("Unsupported transaction type [" + type.name() + "] during fetch from HSQLDB repository");
try {
- return (TransactionData) subclassInfos[type.value].fromBaseMethod.invoke(txRepository, signature, reference, creatorPublicKey, timestamp, fee);
+ // params: long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature
+ return (TransactionData) subclassInfos[type.value].fromBaseMethod.invoke(txRepository, timestamp, txGroupId, reference, creatorPublicKey, fee, signature);
} catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
throw new DataException("Unsupported transaction type [" + type.name() + "] during fetch from HSQLDB repository");
}
@@ -484,6 +488,77 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
}
}
+ @Override
+ public int countTransactionApprovals(int txGroupId, byte[] signature) throws DataException {
+ // Fetch total number of approvals for signature
+ // NOT simply number of GROUP_APPROVAL transactions as some may be rejecting transaction, or changed opinions
+ // Also make sure that GROUP_APPROVAL transaction's admin is still an admin of group
+
+ // Sub-query SQL to find latest GroupApprovalTransaction relating to passed signature
+ String latestApprovalSql = "SELECT admin AS creator, MAX(creation) AS creation FROM GroupApprovalTransactions NATURAL JOIN Transactions WHERE pending_signature = ? GROUP BY admin";
+
+ String sql = "SELECT COUNT(*) FROM "
+ + "(" + latestApprovalSql + ") "
+ + "NATURAL JOIN Transactions "
+ + "NATURAL JOIN GroupApprovalTransactions "
+ + "LEFT OUTER JOIN BlockTransactions ON BlockTransactions.transaction_signature = Transactions.signature "
+ + "LEFT OUTER JOIN Accounts ON Accounts.public_key = GroupApprovalTransactions.admin "
+ + "LEFT OUTER JOIN GroupAdmins ON GroupAdmins.admin = Accounts.account "
+ + "WHERE approval = TRUE AND GroupAdmins.group_id = ?";
+
+ try (ResultSet resultSet = this.repository.checkedExecute(sql, signature, txGroupId)) {
+ return resultSet.getInt(1);
+ } catch (SQLException e) {
+ throw new DataException("Unable to count transaction group-admin approvals from repository", e);
+ }
+ }
+
+ @Override
+ public List getLatestApprovals(byte[] pendingSignature, byte[] adminPublicKey) throws DataException {
+ // Fetch latest approvals for signature
+ // NOT simply number of GROUP_APPROVAL transactions as some may be rejecting transaction, or changed opinions
+ // Also make sure that GROUP_APPROVAL transaction's admin is still an admin of group
+
+ Object[] bindArgs;
+
+ // Sub-query SQL to find latest GroupApprovalTransaction relating to passed signature
+ String latestApprovalSql = "SELECT admin AS creator, MAX(creation) AS creation FROM GroupApprovalTransactions NATURAL JOIN Transactions WHERE pending_signature = ? ";
+ if (adminPublicKey != null)
+ latestApprovalSql += "AND admin = ? ";
+ latestApprovalSql += "GROUP BY admin";
+
+ String sql = "SELECT signature FROM "
+ + "(" + latestApprovalSql + ") "
+ + "NATURAL JOIN Transactions "
+ + "NATURAL JOIN GroupApprovalTransactions "
+ + "LEFT OUTER JOIN BlockTransactions ON BlockTransactions.transaction_signature = Transactions.signature "
+ + "LEFT OUTER JOIN Accounts ON Accounts.public_key = GroupApprovalTransactions.admin "
+ + "LEFT OUTER JOIN GroupAdmins ON GroupAdmins.admin = Accounts.account "
+ + "WHERE approval = TRUE AND GroupAdmins.group_id = Transactions.tx_group_id";
+
+ if (adminPublicKey != null)
+ bindArgs = new Object[] { pendingSignature, adminPublicKey };
+ else
+ bindArgs = new Object[] { pendingSignature };
+
+ List approvals = new ArrayList<>();
+
+ try (ResultSet resultSet = this.repository.checkedExecute(sql, bindArgs)) {
+ if (resultSet == null)
+ return approvals;
+
+ do {
+ byte[] signature = resultSet.getBytes(1);
+
+ approvals.add((GroupApprovalTransactionData) this.fromSignature(signature));
+ } while (resultSet.next());
+
+ return approvals;
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch latest transaction group-admin approvals from repository", e);
+ }
+ }
+
@Override
public boolean isConfirmed(byte[] signature) throws DataException {
try {
@@ -553,7 +628,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
HSQLDBSaver saver = new HSQLDBSaver("Transactions");
saver.bind("signature", transactionData.getSignature()).bind("reference", transactionData.getReference()).bind("type", transactionData.getType().value)
.bind("creator", transactionData.getCreatorPublicKey()).bind("creation", new Timestamp(transactionData.getTimestamp()))
- .bind("fee", transactionData.getFee()).bind("milestone_block", null);
+ .bind("fee", transactionData.getFee()).bind("milestone_block", null).bind("tx_group_id", transactionData.getTxGroupId());
try {
saver.execute(this.repository);
} catch (SQLException e) {
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java
index 21317700..c11a503d 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBTransferAssetTransactionRepository.java
@@ -16,18 +16,17 @@ public class HSQLDBTransferAssetTransactionRepository extends HSQLDBTransactionR
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
- .checkedExecute("SELECT sender, recipient, asset_id, amount FROM TransferAssetTransactions WHERE signature = ?", signature)) {
+ .checkedExecute("SELECT recipient, asset_id, amount FROM TransferAssetTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
return null;
- byte[] senderPublicKey = resultSet.getBytes(1);
- String recipient = resultSet.getString(2);
- long assetId = resultSet.getLong(3);
- BigDecimal amount = resultSet.getBigDecimal(4);
+ String recipient = resultSet.getString(1);
+ long assetId = resultSet.getLong(2);
+ BigDecimal amount = resultSet.getBigDecimal(3);
- return new TransferAssetTransactionData(senderPublicKey, recipient, amount, assetId, fee, timestamp, reference, signature);
+ return new TransferAssetTransactionData(timestamp, txGroupId, reference, creatorPublicKey, recipient, amount, assetId, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch transfer asset transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateGroupTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateGroupTransactionRepository.java
index 3efb14c5..47e25373 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateGroupTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateGroupTransactionRepository.java
@@ -5,6 +5,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import org.qora.data.transaction.UpdateGroupTransactionData;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.data.transaction.TransactionData;
import org.qora.repository.DataException;
import org.qora.repository.hsqldb.HSQLDBRepository;
@@ -16,9 +17,10 @@ public class HSQLDBUpdateGroupTransactionRepository extends HSQLDBTransactionRep
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute(
- "SELECT group_id, new_owner, new_description, new_is_open, group_reference FROM UpdateGroupTransactions WHERE signature = ?", signature)) {
+ "SELECT group_id, new_owner, new_description, new_is_open, new_approval_threshold, group_reference FROM UpdateGroupTransactions WHERE signature = ?",
+ signature)) {
if (resultSet == null)
return null;
@@ -26,10 +28,11 @@ public class HSQLDBUpdateGroupTransactionRepository extends HSQLDBTransactionRep
String newOwner = resultSet.getString(2);
String newDescription = resultSet.getString(3);
boolean newIsOpen = resultSet.getBoolean(4);
- byte[] groupReference = resultSet.getBytes(5);
+ ApprovalThreshold newApprovalThreshold = ApprovalThreshold.valueOf(resultSet.getInt(5));
+ byte[] groupReference = resultSet.getBytes(6);
- return new UpdateGroupTransactionData(creatorPublicKey, groupId, newOwner, newDescription, newIsOpen, groupReference, fee, timestamp, reference,
- signature);
+ return new UpdateGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, groupId, newOwner, newDescription, newIsOpen,
+ newApprovalThreshold, groupReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch update group transaction from repository", e);
}
@@ -44,6 +47,7 @@ public class HSQLDBUpdateGroupTransactionRepository extends HSQLDBTransactionRep
saveHelper.bind("signature", updateGroupTransactionData.getSignature()).bind("owner", updateGroupTransactionData.getOwnerPublicKey())
.bind("group_id", updateGroupTransactionData.getGroupId()).bind("new_owner", updateGroupTransactionData.getNewOwner())
.bind("new_description", updateGroupTransactionData.getNewDescription()).bind("new_is_open", updateGroupTransactionData.getNewIsOpen())
+ .bind("new_approval_threshold", updateGroupTransactionData.getNewApprovalThreshold().value)
.bind("group_reference", updateGroupTransactionData.getGroupReference());
try {
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java
index be088143..788dc97f 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBUpdateNameTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBUpdateNameTransactionRepository extends HSQLDBTransactionRepo
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] ownerPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT new_owner, name, new_data, name_reference FROM UpdateNameTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -27,7 +27,7 @@ public class HSQLDBUpdateNameTransactionRepository extends HSQLDBTransactionRepo
String newData = resultSet.getString(3);
byte[] nameReference = resultSet.getBytes(4);
- return new UpdateNameTransactionData(ownerPublicKey, newOwner, name, newData, nameReference, fee, timestamp, reference, signature);
+ return new UpdateNameTransactionData(timestamp, txGroupId, reference, creatorPublicKey, newOwner, name, newData, nameReference, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch update name transaction from repository", e);
}
diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java
index 7dd9c3f8..077f845c 100644
--- a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java
+++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBVoteOnPollTransactionRepository.java
@@ -16,7 +16,7 @@ public class HSQLDBVoteOnPollTransactionRepository extends HSQLDBTransactionRepo
this.repository = repository;
}
- TransactionData fromBase(byte[] signature, byte[] reference, byte[] creatorPublicKey, long timestamp, BigDecimal fee) throws DataException {
+ TransactionData fromBase(long timestamp, int txGroupId, byte[] reference, byte[] creatorPublicKey, BigDecimal fee, byte[] signature) throws DataException {
try (ResultSet resultSet = this.repository
.checkedExecute("SELECT poll_name, option_index, previous_option_index FROM VoteOnPollTransactions WHERE signature = ?", signature)) {
if (resultSet == null)
@@ -30,7 +30,7 @@ public class HSQLDBVoteOnPollTransactionRepository extends HSQLDBTransactionRepo
if (resultSet.wasNull())
previousOptionIndex = null;
- return new VoteOnPollTransactionData(creatorPublicKey, pollName, optionIndex, previousOptionIndex, fee, timestamp, reference, signature);
+ return new VoteOnPollTransactionData(timestamp, txGroupId, reference, creatorPublicKey, pollName, optionIndex, previousOptionIndex, fee, signature);
} catch (SQLException e) {
throw new DataException("Unable to fetch vote on poll transaction from repository", e);
}
diff --git a/src/main/java/org/qora/settings/Settings.java b/src/main/java/org/qora/settings/Settings.java
index 463c4790..54a92fd8 100644
--- a/src/main/java/org/qora/settings/Settings.java
+++ b/src/main/java/org/qora/settings/Settings.java
@@ -26,7 +26,7 @@ public class Settings {
private static Settings instance;
private String userpath = "";
private boolean useBitcoinTestNet = false;
- private boolean wipeUnconfirmedOnStart = true;
+ private boolean wipeUnconfirmedOnStart = false;
private String blockchainConfigPath = "blockchain.json";
/** Maximum number of unconfirmed transactions allowed per account */
private int maxUnconfirmedPerAccount = 100;
diff --git a/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java b/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java
index 4b703581..7ecc2ee1 100644
--- a/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java
+++ b/src/main/java/org/qora/transaction/AddGroupAdminTransaction.java
@@ -84,6 +84,10 @@ public class AddGroupAdminTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != addGroupAdminTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account owner = getOwner();
// Check transaction's public key matches group's current owner
diff --git a/src/main/java/org/qora/transaction/ATTransaction.java b/src/main/java/org/qora/transaction/AtTransaction.java
similarity index 98%
rename from src/main/java/org/qora/transaction/ATTransaction.java
rename to src/main/java/org/qora/transaction/AtTransaction.java
index 92ce728c..3babce38 100644
--- a/src/main/java/org/qora/transaction/ATTransaction.java
+++ b/src/main/java/org/qora/transaction/AtTransaction.java
@@ -19,7 +19,7 @@ import org.qora.transform.transaction.AtTransactionTransformer;
import com.google.common.primitives.Bytes;
-public class ATTransaction extends Transaction {
+public class AtTransaction extends Transaction {
// Properties
private ATTransactionData atTransactionData;
@@ -29,7 +29,7 @@ public class ATTransaction extends Transaction {
// Constructors
- public ATTransaction(Repository repository, TransactionData transactionData) {
+ public AtTransaction(Repository repository, TransactionData transactionData) {
super(repository, transactionData);
this.atTransactionData = (ATTransactionData) this.transactionData;
diff --git a/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java b/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java
index 79ccf456..92b18853 100644
--- a/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java
+++ b/src/main/java/org/qora/transaction/CancelGroupBanTransaction.java
@@ -84,6 +84,10 @@ public class CancelGroupBanTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != groupUnbanTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account admin = getAdmin();
// Can't unban if not an admin
diff --git a/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java b/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java
index d4cbe20b..cd725f82 100644
--- a/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java
+++ b/src/main/java/org/qora/transaction/CancelGroupInviteTransaction.java
@@ -84,6 +84,10 @@ public class CancelGroupInviteTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != cancelGroupInviteTransactionData.getGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account admin = getAdmin();
// Check admin is actually an admin
diff --git a/src/main/java/org/qora/transaction/CreateGroupTransaction.java b/src/main/java/org/qora/transaction/CreateGroupTransaction.java
index 5671469e..5bb29987 100644
--- a/src/main/java/org/qora/transaction/CreateGroupTransaction.java
+++ b/src/main/java/org/qora/transaction/CreateGroupTransaction.java
@@ -74,6 +74,10 @@ public class CreateGroupTransaction extends Transaction {
if (!Crypto.isValidAddress(createGroupTransactionData.getOwner()))
return ValidationResult.INVALID_ADDRESS;
+ // Check approval threshold is valid
+ if (createGroupTransactionData.getApprovalThreshold() == null)
+ return ValidationResult.INVALID_GROUP_APPROVAL_THRESHOLD;
+
// Check group name size bounds
int groupNameLength = Utf8.encodedLength(createGroupTransactionData.getGroupName());
if (groupNameLength < 1 || groupNameLength > Group.MAX_NAME_SIZE)
diff --git a/src/main/java/org/qora/transaction/DeployAtTransaction.java b/src/main/java/org/qora/transaction/DeployAtTransaction.java
index d420bb9e..d30c8ccd 100644
--- a/src/main/java/org/qora/transaction/DeployAtTransaction.java
+++ b/src/main/java/org/qora/transaction/DeployAtTransaction.java
@@ -86,7 +86,7 @@ public class DeployAtTransaction extends Transaction {
/** Make sure deployATTransactionData has an ATAddress */
private void ensureATAddress() throws DataException {
- if (this.deployATTransactionData.getATAddress() != null)
+ if (this.deployATTransactionData.getAtAddress() != null)
return;
int blockHeight = this.getHeight();
@@ -112,7 +112,7 @@ public class DeployAtTransaction extends Transaction {
String atAddress = Crypto.toATAddress(byteBuffer.array());
- this.deployATTransactionData.setATAddress(atAddress);
+ this.deployATTransactionData.setAtAddress(atAddress);
} catch (UnsupportedEncodingException e) {
throw new DataException("Unable to generate AT account from Deploy AT transaction data", e);
}
@@ -123,7 +123,7 @@ public class DeployAtTransaction extends Transaction {
public Account getATAccount() throws DataException {
ensureATAddress();
- return new Account(this.repository, this.deployATTransactionData.getATAddress());
+ return new Account(this.repository, this.deployATTransactionData.getAtAddress());
}
// Processing
@@ -144,7 +144,7 @@ public class DeployAtTransaction extends Transaction {
return ValidationResult.INVALID_DESCRIPTION_LENGTH;
// Check AT-type size bounds
- int ATTypeLength = Utf8.encodedLength(deployATTransactionData.getATType());
+ int ATTypeLength = Utf8.encodedLength(deployATTransactionData.getAtType());
if (ATTypeLength < 1 || ATTypeLength > MAX_AT_TYPE_SIZE)
return ValidationResult.INVALID_AT_TYPE_LENGTH;
@@ -257,7 +257,7 @@ public class DeployAtTransaction extends Transaction {
creator.setLastReference(deployATTransactionData.getReference());
// Delete AT's account (and hence its balance)
- this.repository.getAccountRepository().delete(this.deployATTransactionData.getATAddress());
+ this.repository.getAccountRepository().delete(this.deployATTransactionData.getAtAddress());
}
}
diff --git a/src/main/java/org/qora/transaction/GroupApprovalTransaction.java b/src/main/java/org/qora/transaction/GroupApprovalTransaction.java
new file mode 100644
index 00000000..03677b1d
--- /dev/null
+++ b/src/main/java/org/qora/transaction/GroupApprovalTransaction.java
@@ -0,0 +1,136 @@
+package org.qora.transaction;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.qora.account.Account;
+import org.qora.account.PublicKeyAccount;
+import org.qora.asset.Asset;
+import org.qora.data.transaction.GroupApprovalTransactionData;
+import org.qora.data.transaction.TransactionData;
+import org.qora.repository.DataException;
+import org.qora.repository.Repository;
+
+public class GroupApprovalTransaction extends Transaction {
+
+ // Properties
+ private GroupApprovalTransactionData groupApprovalTransactionData;
+
+ // Constructors
+
+ public GroupApprovalTransaction(Repository repository, TransactionData transactionData) {
+ super(repository, transactionData);
+
+ this.groupApprovalTransactionData = (GroupApprovalTransactionData) this.transactionData;
+ }
+
+ // More information
+
+ @Override
+ public List getRecipientAccounts() throws DataException {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isInvolved(Account account) throws DataException {
+ String address = account.getAddress();
+
+ if (address.equals(this.getAdmin().getAddress()))
+ return true;
+
+ return false;
+ }
+
+ @Override
+ public BigDecimal getAmount(Account account) throws DataException {
+ String address = account.getAddress();
+ BigDecimal amount = BigDecimal.ZERO.setScale(8);
+
+ if (address.equals(this.getAdmin().getAddress()))
+ amount = amount.subtract(this.transactionData.getFee());
+
+ return amount;
+ }
+
+ // Navigation
+
+ public Account getAdmin() throws DataException {
+ return new PublicKeyAccount(this.repository, this.groupApprovalTransactionData.getAdminPublicKey());
+ }
+
+ // Processing
+
+ @Override
+ public ValidationResult isValid() throws DataException {
+ // Grab pending transaction's data
+ TransactionData pendingTransactionData = this.repository.getTransactionRepository().fromSignature(groupApprovalTransactionData.getPendingSignature());
+ if (pendingTransactionData == null)
+ return ValidationResult.TRANSACTION_UNKNOWN;
+
+ // Check pending transaction is not already in a block
+ if (this.repository.getTransactionRepository().getHeightFromSignature(groupApprovalTransactionData.getPendingSignature()) != 0)
+ return ValidationResult.TRANSACTION_ALREADY_CONFIRMED;
+
+ // Check pending transaction's groupID matches our transaction's groupID
+ int effectiveTxGroupId = this.getEffectiveGroupId();
+ if (effectiveTxGroupId != pendingTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
+ Account admin = getAdmin();
+
+ // Can't cast approval decision if not an admin
+ if (!this.repository.getGroupRepository().adminExists(groupApprovalTransactionData.getTxGroupId(), admin.getAddress()))
+ return ValidationResult.NOT_GROUP_ADMIN;
+
+ // Check fee is positive
+ if (groupApprovalTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
+ return ValidationResult.NEGATIVE_FEE;
+
+ // Check reference
+ if (!Arrays.equals(admin.getLastReference(), groupApprovalTransactionData.getReference()))
+ return ValidationResult.INVALID_REFERENCE;
+
+ // Check creator has enough funds
+ if (admin.getConfirmedBalance(Asset.QORA).compareTo(groupApprovalTransactionData.getFee()) < 0)
+ return ValidationResult.NO_BALANCE;
+
+ return ValidationResult.OK;
+ }
+
+ @Override
+ public void process() throws DataException {
+ // Find previous approval decision (if any) by this admin for pending transaction
+ List approvals = this.repository.getTransactionRepository().getLatestApprovals(groupApprovalTransactionData.getPendingSignature(), groupApprovalTransactionData.getAdminPublicKey());
+
+ if (!approvals.isEmpty())
+ groupApprovalTransactionData.setPriorReference(approvals.get(0).getSignature());
+
+ // Save this transaction with updated prior reference to transaction that can help restore state
+ this.repository.getTransactionRepository().save(groupApprovalTransactionData);
+
+ // Update admin's balance
+ Account admin = getAdmin();
+ admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).subtract(groupApprovalTransactionData.getFee()));
+
+ // Update admin's reference
+ admin.setLastReference(groupApprovalTransactionData.getSignature());
+ }
+
+ @Override
+ public void orphan() throws DataException {
+ // Revert?
+
+ // Delete this transaction itself
+ this.repository.getTransactionRepository().delete(groupApprovalTransactionData);
+
+ // Update admin's balance
+ Account admin = getAdmin();
+ admin.setConfirmedBalance(Asset.QORA, admin.getConfirmedBalance(Asset.QORA).add(groupApprovalTransactionData.getFee()));
+
+ // Update admin's reference
+ admin.setLastReference(groupApprovalTransactionData.getReference());
+ }
+
+}
diff --git a/src/main/java/org/qora/transaction/GroupBanTransaction.java b/src/main/java/org/qora/transaction/GroupBanTransaction.java
index 12bb4883..3aa1e21a 100644
--- a/src/main/java/org/qora/transaction/GroupBanTransaction.java
+++ b/src/main/java/org/qora/transaction/GroupBanTransaction.java
@@ -84,6 +84,10 @@ public class GroupBanTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != groupBanTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account admin = getAdmin();
// Can't ban if not an admin
diff --git a/src/main/java/org/qora/transaction/GroupInviteTransaction.java b/src/main/java/org/qora/transaction/GroupInviteTransaction.java
index 47019cdc..6278ecb9 100644
--- a/src/main/java/org/qora/transaction/GroupInviteTransaction.java
+++ b/src/main/java/org/qora/transaction/GroupInviteTransaction.java
@@ -88,6 +88,11 @@ public class GroupInviteTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ int effectiveTxGroupId = this.getEffectiveGroupId();
+ if (effectiveTxGroupId != groupInviteTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account admin = getAdmin();
// Can't invite if not an admin
diff --git a/src/main/java/org/qora/transaction/GroupKickTransaction.java b/src/main/java/org/qora/transaction/GroupKickTransaction.java
index 5063656e..4d632e19 100644
--- a/src/main/java/org/qora/transaction/GroupKickTransaction.java
+++ b/src/main/java/org/qora/transaction/GroupKickTransaction.java
@@ -87,6 +87,10 @@ public class GroupKickTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != groupKickTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account admin = getAdmin();
// Can't kick if not an admin
diff --git a/src/main/java/org/qora/transaction/LeaveGroupTransaction.java b/src/main/java/org/qora/transaction/LeaveGroupTransaction.java
index 6f79e42c..f25d4bd9 100644
--- a/src/main/java/org/qora/transaction/LeaveGroupTransaction.java
+++ b/src/main/java/org/qora/transaction/LeaveGroupTransaction.java
@@ -72,6 +72,10 @@ public class LeaveGroupTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != leaveGroupTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account leaver = getLeaver();
// Can't leave if group owner
diff --git a/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java b/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java
index 412c1969..40dec872 100644
--- a/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java
+++ b/src/main/java/org/qora/transaction/RemoveGroupAdminTransaction.java
@@ -84,6 +84,10 @@ public class RemoveGroupAdminTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != removeGroupAdminTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account owner = getOwner();
// Check transaction's public key matches group's current owner
diff --git a/src/main/java/org/qora/transaction/SetGroupTransaction.java b/src/main/java/org/qora/transaction/SetGroupTransaction.java
new file mode 100644
index 00000000..4f3402af
--- /dev/null
+++ b/src/main/java/org/qora/transaction/SetGroupTransaction.java
@@ -0,0 +1,135 @@
+package org.qora.transaction;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.qora.account.Account;
+import org.qora.asset.Asset;
+import org.qora.data.transaction.SetGroupTransactionData;
+import org.qora.data.group.GroupData;
+import org.qora.data.transaction.TransactionData;
+import org.qora.group.Group;
+import org.qora.repository.DataException;
+import org.qora.repository.Repository;
+
+public class SetGroupTransaction extends Transaction {
+
+ // Properties
+ private SetGroupTransactionData setGroupTransactionData;
+
+ // Constructors
+
+ public SetGroupTransaction(Repository repository, TransactionData transactionData) {
+ super(repository, transactionData);
+
+ this.setGroupTransactionData = (SetGroupTransactionData) this.transactionData;
+ }
+
+ // More information
+
+ @Override
+ public List getRecipientAccounts() throws DataException {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean isInvolved(Account account) throws DataException {
+ String address = account.getAddress();
+
+ if (address.equals(this.getCreator().getAddress()))
+ return true;
+
+ return false;
+ }
+
+ @Override
+ public BigDecimal getAmount(Account account) throws DataException {
+ String address = account.getAddress();
+ BigDecimal amount = BigDecimal.ZERO.setScale(8);
+
+ if (address.equals(this.getCreator().getAddress()))
+ amount = amount.subtract(this.transactionData.getFee());
+
+ return amount;
+ }
+
+ // Navigation
+
+ // Processing
+
+ @Override
+ public ValidationResult isValid() throws DataException {
+ GroupData groupData = this.repository.getGroupRepository().fromGroupId(setGroupTransactionData.getDefaultGroupId());
+
+ // Check group exists
+ if (groupData == null)
+ return ValidationResult.GROUP_DOES_NOT_EXIST;
+
+ Account creator = getCreator();
+
+ // Must be member of group
+ if (!this.repository.getGroupRepository().memberExists(setGroupTransactionData.getDefaultGroupId(), creator.getAddress()))
+ return ValidationResult.NOT_GROUP_MEMBER;
+
+ // Check fee is positive
+ if (setGroupTransactionData.getFee().compareTo(BigDecimal.ZERO) <= 0)
+ return ValidationResult.NEGATIVE_FEE;
+
+ // Check reference
+ if (!Arrays.equals(creator.getLastReference(), setGroupTransactionData.getReference()))
+ return ValidationResult.INVALID_REFERENCE;
+
+ // Check creator has enough funds
+ if (creator.getConfirmedBalance(Asset.QORA).compareTo(setGroupTransactionData.getFee()) < 0)
+ return ValidationResult.NO_BALANCE;
+
+ return ValidationResult.OK;
+ }
+
+ @Override
+ public void process() throws DataException {
+ Account creator = getCreator();
+
+ Integer previousDefaultGroupId = this.repository.getAccountRepository().getDefaultGroupId(creator.getAddress());
+ if (previousDefaultGroupId == null)
+ previousDefaultGroupId = Group.DEFAULT_GROUP;
+
+ setGroupTransactionData.setPreviousDefaultGroupId(previousDefaultGroupId);
+
+ // Save this transaction with account's previous defaultGroupId value
+ this.repository.getTransactionRepository().save(setGroupTransactionData);
+
+ // Set account's new default groupID
+ creator.setDefaultGroupId(setGroupTransactionData.getDefaultGroupId());
+
+ // Update creator's balance
+ creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).subtract(setGroupTransactionData.getFee()));
+
+ // Update admin's reference
+ creator.setLastReference(setGroupTransactionData.getSignature());
+ }
+
+ @Override
+ public void orphan() throws DataException {
+ // Revert
+ Account creator = getCreator();
+
+ Integer previousDefaultGroupId = setGroupTransactionData.getPreviousDefaultGroupId();
+ if (previousDefaultGroupId == null)
+ previousDefaultGroupId = Group.DEFAULT_GROUP;
+
+ creator.setDefaultGroupId(previousDefaultGroupId);
+
+ // Delete this transaction itself
+ this.repository.getTransactionRepository().delete(setGroupTransactionData);
+
+ // Update creator's balance
+ creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(setGroupTransactionData.getFee()));
+
+ // Update admin's reference
+ creator.setLastReference(setGroupTransactionData.getReference());
+ }
+
+}
diff --git a/src/main/java/org/qora/transaction/Transaction.java b/src/main/java/org/qora/transaction/Transaction.java
index 4e5754ac..6c78185a 100644
--- a/src/main/java/org/qora/transaction/Transaction.java
+++ b/src/main/java/org/qora/transaction/Transaction.java
@@ -17,12 +17,13 @@ import org.qora.account.PublicKeyAccount;
import org.qora.block.BlockChain;
import org.qora.data.block.BlockData;
import org.qora.data.transaction.TransactionData;
+import org.qora.group.Group;
import org.qora.repository.DataException;
+import org.qora.repository.GroupRepository;
import org.qora.repository.Repository;
import org.qora.settings.Settings;
import org.qora.transform.TransformationException;
import org.qora.transform.transaction.TransactionTransformer;
-import org.qora.utils.Base58;
import org.qora.utils.NTP;
import static java.util.Arrays.stream;
@@ -36,40 +37,43 @@ public abstract class Transaction {
// Transaction types
public enum TransactionType {
// NOTE: must be contiguous or reflection fails
- GENESIS(1),
- PAYMENT(2),
- REGISTER_NAME(3),
- UPDATE_NAME(4),
- SELL_NAME(5),
- CANCEL_SELL_NAME(6),
- BUY_NAME(7),
- CREATE_POLL(8),
- VOTE_ON_POLL(9),
- ARBITRARY(10),
- ISSUE_ASSET(11),
- TRANSFER_ASSET(12),
- CREATE_ASSET_ORDER(13),
- CANCEL_ASSET_ORDER(14),
- MULTI_PAYMENT(15),
- DEPLOY_AT(16),
- MESSAGE(17),
- DELEGATION(18),
- SUPERNODE(19),
- AIRDROP(20),
- AT(21),
- CREATE_GROUP(22),
- UPDATE_GROUP(23),
- ADD_GROUP_ADMIN(24),
- REMOVE_GROUP_ADMIN(25),
- GROUP_BAN(26),
- CANCEL_GROUP_BAN(27),
- GROUP_KICK(28),
- GROUP_INVITE(29),
- CANCEL_GROUP_INVITE(30),
- JOIN_GROUP(31),
- LEAVE_GROUP(32);
+ GENESIS(1, true),
+ PAYMENT(2, false),
+ REGISTER_NAME(3, false),
+ UPDATE_NAME(4, false),
+ SELL_NAME(5, false),
+ CANCEL_SELL_NAME(6, false),
+ BUY_NAME(7, false),
+ CREATE_POLL(8, false),
+ VOTE_ON_POLL(9, false),
+ ARBITRARY(10, false),
+ ISSUE_ASSET(11, false),
+ TRANSFER_ASSET(12, false),
+ CREATE_ASSET_ORDER(13, false),
+ CANCEL_ASSET_ORDER(14, false),
+ MULTI_PAYMENT(15, false),
+ DEPLOY_AT(16, false),
+ MESSAGE(17, false),
+ DELEGATION(18, false),
+ SUPERNODE(19, false),
+ AIRDROP(20, true),
+ AT(21, true),
+ CREATE_GROUP(22, false),
+ UPDATE_GROUP(23, true),
+ ADD_GROUP_ADMIN(24, true),
+ REMOVE_GROUP_ADMIN(25, true),
+ GROUP_BAN(26, true),
+ CANCEL_GROUP_BAN(27, true),
+ GROUP_KICK(28, true),
+ GROUP_INVITE(29, true),
+ CANCEL_GROUP_INVITE(30, true),
+ JOIN_GROUP(31, true),
+ LEAVE_GROUP(32, true),
+ GROUP_APPROVAL(33, true),
+ SET_GROUP(34, true);
public final int value;
+ public final boolean skipsApproval;
public final String valueString;
public final String className;
public final Class> clazz;
@@ -77,8 +81,9 @@ public abstract class Transaction {
private final static Map map = stream(TransactionType.values()).collect(toMap(type -> type.value, type -> type));
- TransactionType(int value) {
+ TransactionType(int value, boolean skipsApproval) {
this.value = value;
+ this.skipsApproval = skipsApproval;
this.valueString = String.valueOf(value);
String[] classNameParts = this.name().toLowerCase().split("_");
@@ -173,6 +178,11 @@ public abstract class Transaction {
BAN_UNKNOWN(59),
BANNED_FROM_GROUP(60),
JOIN_REQUEST_EXISTS(61),
+ INVALID_GROUP_APPROVAL_THRESHOLD(62),
+ GROUP_ID_MISMATCH(63),
+ INVALID_GROUP_ID(64),
+ TRANSACTION_UNKNOWN(65),
+ TRANSACTION_ALREADY_CONFIRMED(66),
NOT_YET_RELEASED(1000);
public final int value;
@@ -443,8 +453,7 @@ public abstract class Transaction {
* Returns whether transaction can be added to unconfirmed transactions.
*
* NOTE: temporarily updates creator's lastReference to that from
- * unconfirmed transactions, and hence calls repository.discardChanges()
- * before exit.
+ * unconfirmed transactions, and hence uses a repository savepoint.
*
* This is not done normally because we don't want unconfirmed transactions affecting validity of transactions already included in a block.
*
@@ -462,11 +471,16 @@ public abstract class Transaction {
if (this.transactionData.getTimestamp() > maxTimestamp)
return ValidationResult.TIMESTAMP_TOO_NEW;
+ repository.setSavepoint();
try {
PublicKeyAccount creator = this.getCreator();
if (creator == null)
return ValidationResult.MISSING_CREATOR;
+ // Check transaction's txGroupId
+ if (!this.isValidTxGroupId())
+ return ValidationResult.INVALID_GROUP_ID;
+
creator.setLastReference(creator.getUnconfirmedLastReference());
ValidationResult result = this.isValid();
@@ -476,10 +490,35 @@ public abstract class Transaction {
return result;
} finally {
- repository.discardChanges();
+ repository.rollbackToSavepoint();
}
}
+ private boolean isValidTxGroupId() throws DataException {
+ // Does this transaction type bypass approval?
+ if (this.transactionData.getType().skipsApproval)
+ return true;
+
+ int txGroupId = this.getEffectiveGroupId();
+ if (txGroupId == Group.NO_GROUP)
+ return true;
+
+ Group group = new Group(repository, txGroupId);
+ if (group.getGroupData() == null) {
+ // Group no longer exists? Possibly due to blockchain orphaning undoing group creation?
+ return false;
+ }
+
+ GroupRepository groupRepository = this.repository.getGroupRepository();
+
+ // Is transaction's creator is group member?
+ PublicKeyAccount creator = this.getCreator();
+ if (groupRepository.memberExists(txGroupId, creator.getAddress()))
+ return true;
+
+ return false;
+ }
+
private int countUnconfirmedByCreator(PublicKeyAccount creator) throws DataException {
List unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions();
@@ -499,8 +538,7 @@ public abstract class Transaction {
* Returns sorted, unconfirmed transactions, deleting invalid.
*
* NOTE: temporarily updates accounts' lastReference to that from
- * unconfirmed transactions, and hence calls repository.discardChanges()
- * before exit.
+ * unconfirmed transactions, hence uses a repository savepoint.
*
* @return sorted unconfirmed transactions
* @throws DataException
@@ -508,42 +546,64 @@ public abstract class Transaction {
public static List getUnconfirmedTransactions(Repository repository) throws DataException {
BlockData latestBlockData = repository.getBlockRepository().getLastBlock();
+ List unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions();
+
+ unconfirmedTransactions.sort(getDataComparator());
+
+ repository.setSavepoint();
+ try {
+ for (int i = 0; i < unconfirmedTransactions.size(); ++i) {
+ TransactionData transactionData = unconfirmedTransactions.get(i);
+
+ if (!isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp())) {
+ unconfirmedTransactions.remove(i);
+ --i;
+ continue;
+ }
+ }
+ } finally {
+ // Throw away temporary updates to account lastReference
+ repository.rollbackToSavepoint();
+ }
+
+ return unconfirmedTransactions;
+ }
+
+ public static List getInvalidTransactions(Repository repository) throws DataException {
+ BlockData latestBlockData = repository.getBlockRepository().getLastBlock();
+
List unconfirmedTransactions = repository.getTransactionRepository().getUnconfirmedTransactions();
List invalidTransactions = new ArrayList<>();
unconfirmedTransactions.sort(getDataComparator());
- for (int i = 0; i < unconfirmedTransactions.size(); ++i) {
- TransactionData transactionData = unconfirmedTransactions.get(i);
+ repository.setSavepoint();
+ try {
+ for (int i = 0; i < unconfirmedTransactions.size(); ++i) {
+ TransactionData transactionData = unconfirmedTransactions.get(i);
- if (!isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp())) {
- invalidTransactions.add(transactionData);
+ if (!isStillValidUnconfirmed(repository, transactionData, latestBlockData.getTimestamp())) {
+ invalidTransactions.add(transactionData);
- unconfirmedTransactions.remove(i);
- --i;
- continue;
+ unconfirmedTransactions.remove(i);
+ --i;
+ continue;
+ }
}
+ } finally {
+ // Throw away temporary updates to account lastReference
+ repository.rollbackToSavepoint();
}
- // Throw away temporary updates to account lastReference
- repository.discardChanges();
-
- // Actually delete invalid transactions from database
- for (TransactionData invalidTransactionData : invalidTransactions) {
- LOGGER.trace(String.format("Deleting invalid, unconfirmed transaction %s", Base58.encode(invalidTransactionData.getSignature())));
- repository.getTransactionRepository().delete(invalidTransactionData);
- }
- repository.saveChanges();
-
- return unconfirmedTransactions;
+ return invalidTransactions;
}
/**
* Returns whether transaction is still a valid unconfirmed transaction.
*
* NOTE: temporarily updates creator's lastReference to that from
- * unconfirmed transactions, and hence caller should invoke
- * repository.discardChanges().
+ * unconfirmed transactions, and hence caller should use a repository
+ * savepoint or invoke repository.discardChanges().
*
* @return true if transaction can be added to unconfirmed transactions, false otherwise
* @throws DataException
@@ -567,6 +627,75 @@ public abstract class Transaction {
return true;
}
+ /**
+ * Returns transaction's effective groupID, using default values where necessary.
+ */
+ public int getEffectiveGroupId() throws DataException {
+ int txGroupId = this.transactionData.getTxGroupId();
+
+ // If transaction's groupID is NO_GROUP then group-ness doesn't apply
+ if (txGroupId == Group.NO_GROUP) {
+ if (BlockChain.getInstance().getGrouplessAllowed())
+ return txGroupId;
+ else
+ txGroupId = Group.DEFAULT_GROUP;
+ }
+
+ // If transaction's groupID is not DEFAULT_GROUP then no further processing required
+ if (txGroupId != Group.DEFAULT_GROUP)
+ return txGroupId;
+
+ // Try using account's default groupID
+ PublicKeyAccount creator = this.getCreator();
+ txGroupId = creator.getDefaultGroupId();
+
+ // If transaction's groupID is NO_GROUP then group-ness doesn't apply
+ if (txGroupId == Group.NO_GROUP) {
+ if (BlockChain.getInstance().getGrouplessAllowed())
+ return txGroupId;
+ else
+ txGroupId = Group.DEFAULT_GROUP;
+ }
+
+ // If txGroupId now not DEFAULT_GROUP then no further processing required
+ if (txGroupId != Group.DEFAULT_GROUP)
+ return txGroupId;
+
+ // Still zero? Use blockchain default
+ return BlockChain.getInstance().getDefaultGroupId();
+ }
+
+ /**
+ * Returns whether transaction still requires group-admin approval.
+ *
+ * @throws DataException
+ */
+ public boolean needsGroupApproval() throws DataException {
+ // Does this transaction type bypass approval?
+ if (this.transactionData.getType().skipsApproval)
+ return false;
+
+ int txGroupId = this.getEffectiveGroupId();
+
+ if (txGroupId == Group.NO_GROUP)
+ return false;
+
+ Group group = new Group(repository, txGroupId);
+ if (group.getGroupData() == null) {
+ // Group no longer exists? Possibly due to blockchain orphaning undoing group creation?
+ return true;
+ }
+
+ GroupRepository groupRepository = this.repository.getGroupRepository();
+
+ // If transaction's creator is group admin then auto-approve
+ PublicKeyAccount creator = this.getCreator();
+ if (groupRepository.adminExists(txGroupId, creator.getAddress()))
+ return false;
+
+ return group.getGroupData().getApprovalThreshold().needsApproval(repository, txGroupId, this.transactionData.getSignature());
+ }
+
/**
* Returns whether transaction can be added to the blockchain.
*
diff --git a/src/main/java/org/qora/transaction/UpdateGroupTransaction.java b/src/main/java/org/qora/transaction/UpdateGroupTransaction.java
index ddd9b685..eea0fe6d 100644
--- a/src/main/java/org/qora/transaction/UpdateGroupTransaction.java
+++ b/src/main/java/org/qora/transaction/UpdateGroupTransaction.java
@@ -80,6 +80,10 @@ public class UpdateGroupTransaction extends Transaction {
if (!Crypto.isValidAddress(updateGroupTransactionData.getNewOwner()))
return ValidationResult.INVALID_ADDRESS;
+ // Check new approval threshold is valid
+ if (updateGroupTransactionData.getNewApprovalThreshold() == null)
+ return ValidationResult.INVALID_GROUP_APPROVAL_THRESHOLD;
+
// Check new description size bounds
int newDescriptionLength = Utf8.encodedLength(updateGroupTransactionData.getNewDescription());
if (newDescriptionLength < 1 || newDescriptionLength > Group.MAX_DESCRIPTION_SIZE)
@@ -91,6 +95,10 @@ public class UpdateGroupTransaction extends Transaction {
if (groupData == null)
return ValidationResult.GROUP_DOES_NOT_EXIST;
+ // Check transaction's groupID matches group's ID
+ if (groupData.getGroupId() != updateGroupTransactionData.getTxGroupId())
+ return ValidationResult.GROUP_ID_MISMATCH;
+
Account owner = getOwner();
// Check transaction's public key matches group's current owner
diff --git a/src/main/java/org/qora/transform/Transformer.java b/src/main/java/org/qora/transform/Transformer.java
index 6df49338..bc125d68 100644
--- a/src/main/java/org/qora/transform/Transformer.java
+++ b/src/main/java/org/qora/transform/Transformer.java
@@ -3,6 +3,7 @@ package org.qora.transform;
public abstract class Transformer {
public static final int BOOLEAN_LENGTH = 1;
+ public static final int BYTE_LENGTH = 1;
public static final int INT_LENGTH = 4;
public static final int LONG_LENGTH = 8;
public static final int BIG_DECIMAL_LENGTH = 8;
diff --git a/src/main/java/org/qora/transform/block/BlockTransformer.java b/src/main/java/org/qora/transform/block/BlockTransformer.java
index 748f9368..5cb29e0a 100644
--- a/src/main/java/org/qora/transform/block/BlockTransformer.java
+++ b/src/main/java/org/qora/transform/block/BlockTransformer.java
@@ -8,17 +8,12 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
import org.qora.account.PublicKeyAccount;
-import org.qora.asset.Order;
import org.qora.block.Block;
-import org.qora.data.asset.TradeData;
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.CreateAssetOrderTransaction;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException;
@@ -28,7 +23,6 @@ import org.qora.utils.Base58;
import org.qora.utils.Serialization;
import org.qora.utils.Triple;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Bytes;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
@@ -283,87 +277,6 @@ public class BlockTransformer extends Transformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(Block block) throws TransformationException {
- BlockData blockData = block.getBlockData();
-
- JSONObject json = new JSONObject();
-
- json.put("version", blockData.getVersion());
- json.put("timestamp", blockData.getTimestamp());
- json.put("generatingBalance", blockData.getGeneratingBalance());
- json.put("generator", PublicKeyAccount.getAddress(blockData.getGeneratorPublicKey()));
- json.put("generatorPublicKey", Base58.encode(blockData.getGeneratorPublicKey()));
- json.put("fee", blockData.getTotalFees().toPlainString());
- json.put("transactionsSignature", Base58.encode(blockData.getTransactionsSignature()));
- json.put("generatorSignature", Base58.encode(blockData.getGeneratorSignature()));
- json.put("signature", Base58.encode(blockData.getSignature()));
-
- if (blockData.getReference() != null)
- json.put("reference", Base58.encode(blockData.getReference()));
-
- json.put("height", blockData.getHeight());
-
- // Add transaction info
- JSONArray transactionsJson = new JSONArray();
-
- // XXX this should be moved out to API as it requires repository access
- boolean tradesHappened = false;
-
- try {
- for (Transaction transaction : block.getTransactions()) {
- transactionsJson.add(TransactionTransformer.toJSON(transaction.getTransactionData()));
-
- // If this is an asset CreateOrderTransaction then check to see if any trades happened
- if (transaction.getTransactionData().getType() == Transaction.TransactionType.CREATE_ASSET_ORDER) {
- CreateAssetOrderTransaction orderTransaction = (CreateAssetOrderTransaction) transaction;
- Order order = orderTransaction.getOrder();
- List trades = order.getTrades();
-
- if (trades.stream().anyMatch(tradeData -> Arrays.equals(tradeData.getInitiator(), order.getOrderData().getOrderId()))) {
- tradesHappened = true;
- // No need to check any further
- break;
- }
- }
- }
- } catch (DataException e) {
- throw new TransformationException("Unable to transform block into JSON", e);
- }
- json.put("transactions", transactionsJson);
-
- // Add asset trade activity flag
- json.put("assetTrades", tradesHappened);
-
- // Add CIYAM AT info (if any)
- if (blockData.getATCount() > 0) {
- JSONArray atsJson = new JSONArray();
-
- try {
- for (ATStateData atStateData : block.getATStates()) {
- JSONObject atJson = new JSONObject();
-
- atJson.put("AT", atStateData.getATAddress());
- atJson.put("stateHash", HashCode.fromBytes(atStateData.getStateHash()).toString());
-
- if (blockData.getVersion() >= 4)
- atJson.put("fees", atStateData.getFees().toPlainString());
-
- atsJson.add(atJson);
- }
- } catch (DataException e) {
- throw new TransformationException("Unable to transform block into JSON", e);
- }
-
- json.put("ATs", atsJson);
-
- if (blockData.getVersion() >= 2)
- json.put("atFees", blockData.getATFees());
- }
-
- return json;
- }
-
public static byte[] getBytesForGeneratorSignature(BlockData blockData) throws TransformationException {
byte[] generatorSignature = Arrays.copyOf(blockData.getReference(), GENERATOR_SIGNATURE_LENGTH);
PublicKeyAccount generator = new PublicKeyAccount(null, blockData.getGeneratorPublicKey());
diff --git a/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java
index 69460da3..a2595684 100644
--- a/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/AddGroupAdminTransactionTransformer.java
@@ -5,26 +5,22 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class AddGroupAdminTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + MEMBER_LENGTH;
protected static final TransactionLayout layout;
@@ -32,6 +28,7 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.ADD_GROUP_ADMIN.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group owner's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -43,6 +40,10 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -57,11 +58,11 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new AddGroupAdminTransactionData(ownerPublicKey, groupId, member, fee, timestamp, reference, signature);
+ return new AddGroupAdminTransactionData(timestamp, txGroupId, reference, ownerPublicKey, groupId, member, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -70,12 +71,10 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(addGroupAdminTransactionData.getType().value));
- bytes.write(Longs.toByteArray(addGroupAdminTransactionData.getTimestamp()));
- bytes.write(addGroupAdminTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(addGroupAdminTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(addGroupAdminTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, addGroupAdminTransactionData.getMember());
Serialization.serializeBigDecimal(bytes, addGroupAdminTransactionData.getFee());
@@ -89,25 +88,4 @@ public class AddGroupAdminTransactionTransformer extends TransactionTransformer
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- AddGroupAdminTransactionData addGroupAdminTransactionData = (AddGroupAdminTransactionData) transactionData;
-
- byte[] ownerPublicKey = addGroupAdminTransactionData.getOwnerPublicKey();
-
- json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
- json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
-
- json.put("groupId", addGroupAdminTransactionData.getGroupId());
- json.put("member", addGroupAdminTransactionData.getMember());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java
index e592cb6d..42876a44 100644
--- a/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/ArbitraryTransactionTransformer.java
@@ -8,9 +8,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
import org.qora.block.BlockChain;
import org.qora.data.PaymentData;
import org.qora.data.transaction.ArbitraryTransactionData;
@@ -20,23 +17,17 @@ 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;
import org.qora.utils.Serialization;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class ArbitraryTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int SENDER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int SERVICE_LENGTH = INT_LENGTH;
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
- private static final int PAYMENTS_COUNT_LENGTH = INT_LENGTH;
- 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;
+ private static final int EXTRAS_LENGTH = SERVICE_LENGTH + DATA_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -44,6 +35,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.ARBITRARY.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("sender's public key", TransformationType.PUBLIC_KEY);
layout.add("number of payments", TransformationType.INT);
@@ -64,6 +56,10 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
int version = ArbitraryTransaction.getVersionByTimestamp(timestamp);
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -93,17 +89,20 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new ArbitraryTransactionData(version, senderPublicKey, service, data, DataType.RAW_DATA, payments, fee, timestamp, reference, signature);
+ return new ArbitraryTransactionData(timestamp, txGroupId, reference, senderPublicKey, version, service, data, DataType.RAW_DATA, payments, fee,
+ signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData;
- if (arbitraryTransactionData.getVersion() == 1)
- return TYPE_LENGTH + TYPELESS_DATALESS_LENGTH_V1 + arbitraryTransactionData.getData().length;
- else
- return TYPE_LENGTH + TYPELESS_DATALESS_LENGTH_V3 + arbitraryTransactionData.getData().length
- + arbitraryTransactionData.getPayments().size() * PaymentTransformer.getDataLength();
+ int length = getBaseLength(transactionData) + EXTRAS_LENGTH;
+
+ // V3+ transactions have optional payments
+ if (arbitraryTransactionData.getVersion() >= 3)
+ length += arbitraryTransactionData.getData().length + arbitraryTransactionData.getPayments().size() * PaymentTransformer.getDataLength();
+
+ return length;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -112,11 +111,7 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(arbitraryTransactionData.getType().value));
- bytes.write(Longs.toByteArray(arbitraryTransactionData.getTimestamp()));
- bytes.write(arbitraryTransactionData.getReference());
-
- bytes.write(arbitraryTransactionData.getSenderPublicKey());
+ transformCommonBytes(transactionData, bytes);
if (arbitraryTransactionData.getVersion() != 1) {
List payments = arbitraryTransactionData.getPayments();
@@ -170,36 +165,4 @@ public class ArbitraryTransactionTransformer extends TransactionTransformer {
return Arrays.copyOfRange(bytes, v1Start, bytes.length);
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- ArbitraryTransactionData arbitraryTransactionData = (ArbitraryTransactionData) transactionData;
-
- byte[] senderPublicKey = arbitraryTransactionData.getSenderPublicKey();
-
- json.put("version", arbitraryTransactionData.getVersion());
- json.put("sender", PublicKeyAccount.getAddress(senderPublicKey));
- json.put("senderPublicKey", HashCode.fromBytes(senderPublicKey).toString());
-
- json.put("service", arbitraryTransactionData.getService());
- json.put("data", Base58.encode(arbitraryTransactionData.getData()));
-
- if (arbitraryTransactionData.getVersion() != 1) {
- List payments = arbitraryTransactionData.getPayments();
- JSONArray paymentsJson = new JSONArray();
-
- for (PaymentData paymentData : payments)
- paymentsJson.add(PaymentTransformer.toJSON(paymentData));
-
- json.put("payments", paymentsJson);
- }
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/AtTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/AtTransactionTransformer.java
index 3500f670..5598c815 100644
--- a/src/main/java/org/qora/transform/transaction/AtTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/AtTransactionTransformer.java
@@ -1,94 +1,26 @@
package org.qora.transform.transaction;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.data.transaction.ATTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.transform.TransformationException;
-import org.qora.utils.Serialization;
-
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class AtTransactionTransformer extends TransactionTransformer {
+ protected static final TransactionLayout layout = null;
+
// Property lengths
- private static final int SENDER_LENGTH = ADDRESS_LENGTH;
- private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH;
- private static final int AMOUNT_LENGTH = BIG_DECIMAL_LENGTH;
- private static final int ASSET_ID_LENGTH = LONG_LENGTH;
- private static final int DATA_SIZE_LENGTH = INT_LENGTH;
-
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + ASSET_ID_LENGTH
- + DATA_SIZE_LENGTH;
-
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
throw new TransformationException("Serialized AT Transactions should not exist!");
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- ATTransactionData atTransactionData = (ATTransactionData) transactionData;
-
- return TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + atTransactionData.getMessage().length;
+ // AT Transactions aren't serialized so don't take up any space in the block.
+ return 0;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
- try {
- ATTransactionData atTransactionData = (ATTransactionData) transactionData;
-
- ByteArrayOutputStream bytes = new ByteArrayOutputStream();
-
- bytes.write(Ints.toByteArray(atTransactionData.getType().value));
- bytes.write(Longs.toByteArray(atTransactionData.getTimestamp()));
- bytes.write(atTransactionData.getReference());
-
- Serialization.serializeAddress(bytes, atTransactionData.getATAddress());
-
- Serialization.serializeAddress(bytes, atTransactionData.getRecipient());
-
- // Only emit amount if greater than zero (safer than checking assetId)
- if (atTransactionData.getAmount().compareTo(BigDecimal.ZERO) > 0) {
- Serialization.serializeBigDecimal(bytes, atTransactionData.getAmount());
- bytes.write(Longs.toByteArray(atTransactionData.getAssetId()));
- }
-
- byte[] message = atTransactionData.getMessage();
- if (message.length > 0) {
- bytes.write(Ints.toByteArray(message.length));
- bytes.write(message);
- } else {
- bytes.write(Ints.toByteArray(0));
- }
-
- Serialization.serializeBigDecimal(bytes, atTransactionData.getFee());
-
- if (atTransactionData.getSignature() != null)
- bytes.write(atTransactionData.getSignature());
-
- return bytes.toByteArray();
- } catch (IOException | ClassCastException e) {
- throw new TransformationException(e);
- }
- }
-
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- ATTransactionData atTransactionData = (ATTransactionData) transactionData;
-
- json.put("sender", atTransactionData.getATAddress());
-
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
+ throw new TransformationException("Serialized AT Transactions should not exist!");
}
}
diff --git a/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java
index c27b6c50..8c895dbc 100644
--- a/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/BuyNameTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.BuyNameTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.naming.Name;
@@ -15,19 +14,15 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class BuyNameTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int BUYER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int AMOUNT_LENGTH = BIG_DECIMAL_LENGTH;
private static final int SELLER_LENGTH = ADDRESS_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + BUYER_LENGTH + NAME_SIZE_LENGTH + AMOUNT_LENGTH + SELLER_LENGTH;
+ private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH + AMOUNT_LENGTH + SELLER_LENGTH;
protected static final TransactionLayout layout;
@@ -35,6 +30,7 @@ public class BuyNameTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.BUY_NAME.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("buyer's public key", TransformationType.PUBLIC_KEY);
layout.add("name length", TransformationType.INT);
@@ -48,6 +44,10 @@ public class BuyNameTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -64,15 +64,13 @@ public class BuyNameTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new BuyNameTransactionData(buyerPublicKey, name, amount, seller, fee, timestamp, reference, signature);
+ return new BuyNameTransactionData(timestamp, txGroupId, reference, buyerPublicKey, name, amount, seller, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
BuyNameTransactionData buyNameTransactionData = (BuyNameTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(buyNameTransactionData.getName());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(buyNameTransactionData.getName());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -81,13 +79,12 @@ public class BuyNameTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(buyNameTransactionData.getType().value));
- bytes.write(Longs.toByteArray(buyNameTransactionData.getTimestamp()));
- bytes.write(buyNameTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(buyNameTransactionData.getBuyerPublicKey());
Serialization.serializeSizedString(bytes, buyNameTransactionData.getName());
+
Serialization.serializeBigDecimal(bytes, buyNameTransactionData.getAmount());
+
Serialization.serializeAddress(bytes, buyNameTransactionData.getSeller());
Serialization.serializeBigDecimal(bytes, buyNameTransactionData.getFee());
@@ -101,27 +98,4 @@ public class BuyNameTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- BuyNameTransactionData buyNameTransactionData = (BuyNameTransactionData) transactionData;
-
- byte[] buyerPublicKey = buyNameTransactionData.getBuyerPublicKey();
-
- json.put("buyer", PublicKeyAccount.getAddress(buyerPublicKey));
- json.put("buyerPublicKey", HashCode.fromBytes(buyerPublicKey).toString());
-
- json.put("name", buyNameTransactionData.getName());
- json.put("amount", buyNameTransactionData.getAmount().toPlainString());
-
- json.put("seller", buyNameTransactionData.getSeller());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java
index 0bdab13d..b653941a 100644
--- a/src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CancelAssetOrderTransactionTransformer.java
@@ -5,26 +5,19 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
-
public class CancelAssetOrderTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH;
private static final int ORDER_ID_LENGTH = SIGNATURE_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + ORDER_ID_LENGTH;
+ private static final int EXTRAS_LENGTH = ORDER_ID_LENGTH;
protected static final TransactionLayout layout;
@@ -32,6 +25,7 @@ public class CancelAssetOrderTransactionTransformer extends TransactionTransform
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CANCEL_ASSET_ORDER.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("order creator's public key", TransformationType.PUBLIC_KEY);
layout.add("order ID to cancel", TransformationType.SIGNATURE);
@@ -42,6 +36,10 @@ public class CancelAssetOrderTransactionTransformer extends TransactionTransform
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -55,11 +53,11 @@ public class CancelAssetOrderTransactionTransformer extends TransactionTransform
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CancelAssetOrderTransactionData(creatorPublicKey, orderId, fee, timestamp, reference, signature);
+ return new CancelAssetOrderTransactionData(timestamp, txGroupId, reference, creatorPublicKey, orderId, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -68,11 +66,8 @@ public class CancelAssetOrderTransactionTransformer extends TransactionTransform
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(cancelOrderTransactionData.getType().value));
- bytes.write(Longs.toByteArray(cancelOrderTransactionData.getTimestamp()));
- bytes.write(cancelOrderTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(cancelOrderTransactionData.getCreatorPublicKey());
bytes.write(cancelOrderTransactionData.getOrderId());
Serialization.serializeBigDecimal(bytes, cancelOrderTransactionData.getFee());
@@ -86,24 +81,4 @@ public class CancelAssetOrderTransactionTransformer extends TransactionTransform
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CancelAssetOrderTransactionData cancelOrderTransactionData = (CancelAssetOrderTransactionData) transactionData;
-
- byte[] creatorPublicKey = cancelOrderTransactionData.getCreatorPublicKey();
-
- json.put("creator", PublicKeyAccount.getAddress(creatorPublicKey));
- json.put("creatorPublicKey", HashCode.fromBytes(creatorPublicKey).toString());
-
- json.put("order", Base58.encode(cancelOrderTransactionData.getOrderId()));
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java
index 07ec79f1..4a2317fa 100644
--- a/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CancelGroupBanTransactionTransformer.java
@@ -5,26 +5,22 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class CancelGroupBanTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + MEMBER_LENGTH;
protected static final TransactionLayout layout;
@@ -32,6 +28,7 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CANCEL_GROUP_BAN.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group admin's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -43,6 +40,10 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -57,11 +58,11 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CancelGroupBanTransactionData(adminPublicKey, groupId, member, fee, timestamp, reference, signature);
+ return new CancelGroupBanTransactionData(timestamp, txGroupId, reference, adminPublicKey, groupId, member, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -70,12 +71,10 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(groupUnbanTransactionData.getType().value));
- bytes.write(Longs.toByteArray(groupUnbanTransactionData.getTimestamp()));
- bytes.write(groupUnbanTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(groupUnbanTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(groupUnbanTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, groupUnbanTransactionData.getMember());
Serialization.serializeBigDecimal(bytes, groupUnbanTransactionData.getFee());
@@ -89,25 +88,4 @@ public class CancelGroupBanTransactionTransformer extends TransactionTransformer
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CancelGroupBanTransactionData groupUnbanTransactionData = (CancelGroupBanTransactionData) transactionData;
-
- byte[] adminPublicKey = groupUnbanTransactionData.getAdminPublicKey();
-
- json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
- json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
-
- json.put("groupId", groupUnbanTransactionData.getGroupId());
- json.put("member", groupUnbanTransactionData.getMember());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java
index 1a0f6a77..6c702d7d 100644
--- a/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CancelGroupInviteTransactionTransformer.java
@@ -5,26 +5,22 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class CancelGroupInviteTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int INVITEE_LENGTH = ADDRESS_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + INVITEE_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + INVITEE_LENGTH;
protected static final TransactionLayout layout;
@@ -32,6 +28,7 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CANCEL_GROUP_INVITE.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group admin's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -43,6 +40,10 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -57,11 +58,11 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CancelGroupInviteTransactionData(adminPublicKey, groupId, invitee, fee, timestamp, reference, signature);
+ return new CancelGroupInviteTransactionData(timestamp, txGroupId, reference, adminPublicKey, groupId, invitee, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -70,12 +71,10 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(cancelGroupInviteTransactionData.getType().value));
- bytes.write(Longs.toByteArray(cancelGroupInviteTransactionData.getTimestamp()));
- bytes.write(cancelGroupInviteTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(cancelGroupInviteTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(cancelGroupInviteTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, cancelGroupInviteTransactionData.getInvitee());
Serialization.serializeBigDecimal(bytes, cancelGroupInviteTransactionData.getFee());
@@ -89,25 +88,4 @@ public class CancelGroupInviteTransactionTransformer extends TransactionTransfor
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CancelGroupInviteTransactionData cancelGroupInviteTransactionData = (CancelGroupInviteTransactionData) transactionData;
-
- byte[] adminPublicKey = cancelGroupInviteTransactionData.getAdminPublicKey();
-
- json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
- json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
-
- json.put("groupId", cancelGroupInviteTransactionData.getGroupId());
- json.put("invitee", cancelGroupInviteTransactionData.getInvitee());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
\ No newline at end of file
diff --git a/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java
index 5e4f1d83..15fa07cc 100644
--- a/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CancelSellNameTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.CancelSellNameTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.naming.Name;
@@ -15,17 +14,13 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class CancelSellNameTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH;
+ private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -33,6 +28,7 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CANCEL_SELL_NAME.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("name owner's public key", TransformationType.PUBLIC_KEY);
layout.add("name length", TransformationType.INT);
@@ -44,6 +40,10 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -56,15 +56,13 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CancelSellNameTransactionData(ownerPublicKey, name, fee, timestamp, reference, signature);
+ return new CancelSellNameTransactionData(timestamp, txGroupId, reference, ownerPublicKey, name, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(cancelSellNameTransactionData.getName());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(cancelSellNameTransactionData.getName());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -73,11 +71,8 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(cancelSellNameTransactionData.getType().value));
- bytes.write(Longs.toByteArray(cancelSellNameTransactionData.getTimestamp()));
- bytes.write(cancelSellNameTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(cancelSellNameTransactionData.getOwnerPublicKey());
Serialization.serializeSizedString(bytes, cancelSellNameTransactionData.getName());
Serialization.serializeBigDecimal(bytes, cancelSellNameTransactionData.getFee());
@@ -91,24 +86,4 @@ public class CancelSellNameTransactionTransformer extends TransactionTransformer
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CancelSellNameTransactionData cancelSellNameTransactionData = (CancelSellNameTransactionData) transactionData;
-
- byte[] ownerPublicKey = cancelSellNameTransactionData.getOwnerPublicKey();
-
- json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
- json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
-
- json.put("name", cancelSellNameTransactionData.getName());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java
index bfbb2d28..2cb28685 100644
--- a/src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CreateAssetOrderTransactionTransformer.java
@@ -5,8 +5,6 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
import org.qora.block.BlockChain;
import org.qora.data.transaction.CreateAssetOrderTransactionData;
import org.qora.data.transaction.TransactionData;
@@ -14,18 +12,16 @@ import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
public class CreateAssetOrderTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH;
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
private static final int AMOUNT_LENGTH = 12; // Not standard BIG_DECIMAL_LENGTH
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + (ASSET_ID_LENGTH + AMOUNT_LENGTH) * 2;
+ private static final int EXTRAS_LENGTH = (ASSET_ID_LENGTH + AMOUNT_LENGTH) * 2;
protected static final TransactionLayout layout;
@@ -33,6 +29,7 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CREATE_ASSET_ORDER.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("order creator's public key", TransformationType.PUBLIC_KEY);
layout.add("ID of asset of offer", TransformationType.LONG);
@@ -46,6 +43,10 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -64,11 +65,11 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CreateAssetOrderTransactionData(creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, timestamp, reference, signature);
+ return new CreateAssetOrderTransactionData(timestamp, txGroupId, reference, creatorPublicKey, haveAssetId, wantAssetId, amount, price, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -77,14 +78,14 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(createOrderTransactionData.getType().value));
- bytes.write(Longs.toByteArray(createOrderTransactionData.getTimestamp()));
- bytes.write(createOrderTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(createOrderTransactionData.getCreatorPublicKey());
bytes.write(Longs.toByteArray(createOrderTransactionData.getHaveAssetId()));
+
bytes.write(Longs.toByteArray(createOrderTransactionData.getWantAssetId()));
+
Serialization.serializeBigDecimal(bytes, createOrderTransactionData.getAmount(), AMOUNT_LENGTH);
+
Serialization.serializeBigDecimal(bytes, createOrderTransactionData.getPrice(), AMOUNT_LENGTH);
Serialization.serializeBigDecimal(bytes, createOrderTransactionData.getFee());
@@ -135,30 +136,4 @@ public class CreateAssetOrderTransactionTransformer extends TransactionTransform
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CreateAssetOrderTransactionData createOrderTransactionData = (CreateAssetOrderTransactionData) transactionData;
-
- byte[] creatorPublicKey = createOrderTransactionData.getCreatorPublicKey();
-
- json.put("creator", PublicKeyAccount.getAddress(creatorPublicKey));
- json.put("creatorPublicKey", HashCode.fromBytes(creatorPublicKey).toString());
-
- JSONObject order = new JSONObject();
- order.put("have", createOrderTransactionData.getHaveAssetId());
- order.put("want", createOrderTransactionData.getWantAssetId());
- order.put("amount", createOrderTransactionData.getAmount().toPlainString());
- order.put("price", createOrderTransactionData.getPrice().toPlainString());
-
- json.put("order", order);
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java
index 122e8c74..e3dd313b 100644
--- a/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CreateGroupTransactionTransformer.java
@@ -5,31 +5,27 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.CreateGroupTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class CreateGroupTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH;
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int IS_OPEN_LENGTH = BOOLEAN_LENGTH;
+ private static final int APPROVAL_THRESHOLD_LENGTH = BYTE_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH
- + IS_OPEN_LENGTH;
+ private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + IS_OPEN_LENGTH + APPROVAL_THRESHOLD_LENGTH;
protected static final TransactionLayout layout;
@@ -37,6 +33,7 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CREATE_GROUP.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group creator's public key", TransformationType.PUBLIC_KEY);
layout.add("group's name length", TransformationType.INT);
@@ -44,6 +41,7 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
layout.add("group's description length", TransformationType.INT);
layout.add("group's description", TransformationType.STRING);
layout.add("is group \"open\"?", TransformationType.BOOLEAN);
+ layout.add("group transaction approval threshold", TransformationType.BYTE);
layout.add("fee", TransformationType.AMOUNT);
layout.add("signature", TransformationType.SIGNATURE);
}
@@ -51,6 +49,10 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -64,21 +66,22 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
boolean isOpen = byteBuffer.get() != 0;
+ ApprovalThreshold approvalThreshold = ApprovalThreshold.valueOf(byteBuffer.get());
+
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CreateGroupTransactionData(creatorPublicKey, owner, groupName, description, isOpen, null, fee, timestamp, reference, signature);
+ return new CreateGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, owner, groupName, description, isOpen, approvalThreshold, null,
+ fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
CreateGroupTransactionData createGroupTransactionData = (CreateGroupTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(createGroupTransactionData.getGroupName())
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(createGroupTransactionData.getGroupName())
+ Utf8.encodedLength(createGroupTransactionData.getDescription());
-
- return dataLength;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -87,17 +90,18 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(createGroupTransactionData.getType().value));
- bytes.write(Longs.toByteArray(createGroupTransactionData.getTimestamp()));
- bytes.write(createGroupTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(createGroupTransactionData.getCreatorPublicKey());
Serialization.serializeAddress(bytes, createGroupTransactionData.getOwner());
+
Serialization.serializeSizedString(bytes, createGroupTransactionData.getGroupName());
+
Serialization.serializeSizedString(bytes, createGroupTransactionData.getDescription());
bytes.write((byte) (createGroupTransactionData.getIsOpen() ? 1 : 0));
+ bytes.write((byte) createGroupTransactionData.getApprovalThreshold().value);
+
Serialization.serializeBigDecimal(bytes, createGroupTransactionData.getFee());
if (createGroupTransactionData.getSignature() != null)
@@ -109,27 +113,4 @@ public class CreateGroupTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CreateGroupTransactionData createGroupTransactionData = (CreateGroupTransactionData) transactionData;
-
- byte[] creatorPublicKey = createGroupTransactionData.getCreatorPublicKey();
-
- json.put("creator", PublicKeyAccount.getAddress(creatorPublicKey));
- json.put("creatorPublicKey", HashCode.fromBytes(creatorPublicKey).toString());
-
- json.put("owner", createGroupTransactionData.getOwner());
- json.put("groupName", createGroupTransactionData.getGroupName());
- json.put("description", createGroupTransactionData.getDescription());
- json.put("isOpen", createGroupTransactionData.getIsOpen());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java
index ee7b6aa0..9175ad64 100644
--- a/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/CreatePollTransactionTransformer.java
@@ -7,9 +7,6 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
import org.qora.block.BlockChain;
import org.qora.data.transaction.CreatePollTransactionData;
import org.qora.data.transaction.TransactionData;
@@ -20,21 +17,17 @@ import org.qora.utils.Serialization;
import org.qora.voting.Poll;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class CreatePollTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH;
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int OPTIONS_SIZE_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH
- + OPTIONS_SIZE_LENGTH;
+ private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + OPTIONS_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -42,6 +35,7 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.CREATE_POLL.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("poll creator's public key", TransformationType.PUBLIC_KEY);
layout.add("poll name length", TransformationType.INT);
@@ -58,6 +52,10 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -92,13 +90,13 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new CreatePollTransactionData(creatorPublicKey, owner, pollName, description, pollOptions, fee, timestamp, reference, signature);
+ return new CreatePollTransactionData(timestamp, txGroupId, reference, creatorPublicKey, owner, pollName, description, pollOptions, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
CreatePollTransactionData createPollTransactionData = (CreatePollTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(createPollTransactionData.getPollName())
+ int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(createPollTransactionData.getPollName())
+ Utf8.encodedLength(createPollTransactionData.getDescription());
// Add lengths for each poll options
@@ -120,16 +118,12 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(createPollTransactionData.getType().value));
-
- bytes.write(Longs.toByteArray(createPollTransactionData.getTimestamp()));
-
- bytes.write(createPollTransactionData.getReference());
-
- bytes.write(createPollTransactionData.getCreatorPublicKey());
+ transformCommonBytes(transactionData, bytes);
Serialization.serializeAddress(bytes, createPollTransactionData.getOwner());
+
Serialization.serializeSizedString(bytes, createPollTransactionData.getPollName());
+
Serialization.serializeSizedString(bytes, createPollTransactionData.getDescription());
List pollOptions = createPollTransactionData.getPollOptions();
@@ -178,32 +172,4 @@ public class CreatePollTransactionTransformer extends TransactionTransformer {
return bytes;
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- CreatePollTransactionData createPollTransactionData = (CreatePollTransactionData) transactionData;
-
- byte[] creatorPublicKey = createPollTransactionData.getCreatorPublicKey();
-
- json.put("creator", PublicKeyAccount.getAddress(creatorPublicKey));
- json.put("creatorPublicKey", HashCode.fromBytes(creatorPublicKey).toString());
-
- json.put("owner", createPollTransactionData.getOwner());
- json.put("name", createPollTransactionData.getPollName());
- json.put("description", createPollTransactionData.getDescription());
-
- JSONArray options = new JSONArray();
- for (PollOptionData optionData : createPollTransactionData.getPollOptions())
- options.add(optionData.getOptionName());
-
- json.put("options", options);
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java
index 9317d8e2..6621aec9 100644
--- a/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/DeployAtTransactionTransformer.java
@@ -5,8 +5,6 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-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;
@@ -17,14 +15,12 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
public class DeployAtTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int CREATOR_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int AT_TYPE_SIZE_LENGTH = INT_LENGTH;
@@ -33,9 +29,8 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
private static final int AMOUNT_LENGTH = LONG_LENGTH;
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + CREATOR_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + AT_TYPE_SIZE_LENGTH
- + TAGS_SIZE_LENGTH + CREATION_BYTES_SIZE_LENGTH + AMOUNT_LENGTH;
- private static final int V4_TYPELESS_LENGTH = TYPELESS_LENGTH + ASSET_ID_LENGTH;
+ private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + AT_TYPE_SIZE_LENGTH + TAGS_SIZE_LENGTH + CREATION_BYTES_SIZE_LENGTH
+ + AMOUNT_LENGTH;
protected static final TransactionLayout layout;
@@ -43,6 +38,7 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.DEPLOY_AT.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("AT creator's public key", TransformationType.PUBLIC_KEY);
layout.add("AT name length", TransformationType.INT);
@@ -64,6 +60,10 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
int version = DeployAtTransaction.getVersionByTimestamp(timestamp);
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -95,24 +95,23 @@ 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,
- signature);
+ return new DeployAtTransactionData(timestamp, txGroupId, reference, creatorPublicKey, name, description, ATType, tags, creationBytes, amount, assetId,
+ fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData;
- int dataLength = TYPE_LENGTH;
+ int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH;
int version = DeployAtTransaction.getVersionByTimestamp(transactionData.getTimestamp());
+ // V4+ have assetId too
if (version >= 4)
- dataLength += V4_TYPELESS_LENGTH;
- else
- dataLength += TYPELESS_LENGTH;
+ dataLength += ASSET_ID_LENGTH;
dataLength += Utf8.encodedLength(deployATTransactionData.getName()) + Utf8.encodedLength(deployATTransactionData.getDescription())
- + Utf8.encodedLength(deployATTransactionData.getATType()) + Utf8.encodedLength(deployATTransactionData.getTags())
+ + Utf8.encodedLength(deployATTransactionData.getAtType()) + Utf8.encodedLength(deployATTransactionData.getTags())
+ deployATTransactionData.getCreationBytes().length;
return dataLength;
@@ -126,17 +125,13 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(deployATTransactionData.getType().value));
- bytes.write(Longs.toByteArray(deployATTransactionData.getTimestamp()));
- bytes.write(deployATTransactionData.getReference());
-
- bytes.write(deployATTransactionData.getCreatorPublicKey());
+ transformCommonBytes(transactionData, bytes);
Serialization.serializeSizedString(bytes, deployATTransactionData.getName());
Serialization.serializeSizedString(bytes, deployATTransactionData.getDescription());
- Serialization.serializeSizedString(bytes, deployATTransactionData.getATType());
+ Serialization.serializeSizedString(bytes, deployATTransactionData.getAtType());
Serialization.serializeSizedString(bytes, deployATTransactionData.getTags());
@@ -207,29 +202,4 @@ public class DeployAtTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- DeployAtTransactionData deployATTransactionData = (DeployAtTransactionData) transactionData;
-
- byte[] creatorPublicKey = deployATTransactionData.getCreatorPublicKey();
-
- json.put("creator", PublicKeyAccount.getAddress(creatorPublicKey));
- json.put("creatorPublicKey", HashCode.fromBytes(creatorPublicKey).toString());
- json.put("name", deployATTransactionData.getName());
- json.put("description", deployATTransactionData.getDescription());
- json.put("atType", deployATTransactionData.getATType());
- json.put("tags", deployATTransactionData.getTags());
- json.put("creationBytes", HashCode.fromBytes(deployATTransactionData.getCreationBytes()).toString());
- json.put("amount", deployATTransactionData.getAmount().toPlainString());
- json.put("assetId", deployATTransactionData.getAssetId());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java
index 0448046b..23e7eb60 100644
--- a/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/GenesisTransactionTransformer.java
@@ -5,7 +5,6 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
import org.qora.asset.Asset;
import org.qora.block.BlockChain;
import org.qora.data.transaction.GenesisTransactionData;
@@ -19,15 +18,13 @@ import com.google.common.primitives.Longs;
public class GenesisTransactionTransformer extends TransactionTransformer {
+ // Note that Genesis transactions don't require reference, fee or signature
+
// Property lengths
private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH;
private static final int AMOUNT_LENGTH = LONG_LENGTH;
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
- // Note that Genesis transactions don't require reference, fee or signature:
- 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 {
@@ -37,7 +34,6 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
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);
}
@@ -52,14 +48,15 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
assetId = byteBuffer.getLong();
- return new GenesisTransactionData(recipient, amount, assetId, timestamp);
+ return new GenesisTransactionData(timestamp, recipient, amount, assetId);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
if (transactionData.getTimestamp() < BlockChain.getInstance().getQoraV2Timestamp())
- return TYPE_LENGTH + TYPELESS_LENGTH_V1;
- else
- return TYPE_LENGTH + TYPELESS_LENGTH_V4;
+ return TYPE_LENGTH + TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH;
+
+ // Qora V2+
+ return TYPE_LENGTH + TIMESTAMP_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + ASSET_ID_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -69,9 +66,11 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
bytes.write(Ints.toByteArray(genesisTransactionData.getType().value));
+
bytes.write(Longs.toByteArray(genesisTransactionData.getTimestamp()));
Serialization.serializeAddress(bytes, genesisTransactionData.getRecipient());
+
Serialization.serializeBigDecimal(bytes, genesisTransactionData.getAmount());
if (genesisTransactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp())
@@ -83,21 +82,4 @@ public class GenesisTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- GenesisTransactionData genesisTransactionData = (GenesisTransactionData) transactionData;
-
- json.put("recipient", genesisTransactionData.getRecipient());
- json.put("amount", genesisTransactionData.getAmount().toPlainString());
- json.put("assetId", genesisTransactionData.getAssetId());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/GroupApprovalTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupApprovalTransactionTransformer.java
new file mode 100644
index 00000000..84040e53
--- /dev/null
+++ b/src/main/java/org/qora/transform/transaction/GroupApprovalTransactionTransformer.java
@@ -0,0 +1,90 @@
+package org.qora.transform.transaction;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+
+import org.qora.block.BlockChain;
+import org.qora.data.transaction.GroupApprovalTransactionData;
+import org.qora.data.transaction.TransactionData;
+import org.qora.transaction.Transaction.TransactionType;
+import org.qora.transform.TransformationException;
+import org.qora.utils.Serialization;
+
+public class GroupApprovalTransactionTransformer extends TransactionTransformer {
+
+ // Property lengths
+ private static final int PENDING_SIGNATURE_LENGTH = SIGNATURE_LENGTH;
+ private static final int APPROVAL_LENGTH = BOOLEAN_LENGTH;
+
+ private static final int EXTRAS_LENGTH = PENDING_SIGNATURE_LENGTH + APPROVAL_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("transaction's groupID", TransformationType.INT);
+ layout.add("reference", TransformationType.SIGNATURE);
+ layout.add("group admin's public key", TransformationType.PUBLIC_KEY);
+ layout.add("pending transaction's signature", TransformationType.SIGNATURE);
+ layout.add("approval decision", TransformationType.BOOLEAN);
+ layout.add("fee", TransformationType.AMOUNT);
+ layout.add("signature", TransformationType.SIGNATURE);
+ }
+
+ public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
+ long timestamp = byteBuffer.getLong();
+
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
+ byte[] reference = new byte[REFERENCE_LENGTH];
+ byteBuffer.get(reference);
+
+ byte[] adminPublicKey = Serialization.deserializePublicKey(byteBuffer);
+
+ byte[] pendingSignature = new byte[SIGNATURE_LENGTH];
+ byteBuffer.get(pendingSignature);
+
+ boolean approval = byteBuffer.get() != 0;
+
+ BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
+
+ byte[] signature = new byte[SIGNATURE_LENGTH];
+ byteBuffer.get(signature);
+
+ return new GroupApprovalTransactionData(timestamp, txGroupId, reference, adminPublicKey, pendingSignature, approval, null, fee, signature);
+ }
+
+ public static int getDataLength(TransactionData transactionData) throws TransformationException {
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
+ }
+
+ public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
+ try {
+ GroupApprovalTransactionData groupApprovalTransactionData = (GroupApprovalTransactionData) transactionData;
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+
+ transformCommonBytes(transactionData, bytes);
+
+ bytes.write(groupApprovalTransactionData.getPendingSignature());
+
+ bytes.write((byte) (groupApprovalTransactionData.getApproval() ? 1 : 0));
+
+ Serialization.serializeBigDecimal(bytes, groupApprovalTransactionData.getFee());
+
+ if (groupApprovalTransactionData.getSignature() != null)
+ bytes.write(groupApprovalTransactionData.getSignature());
+
+ return bytes.toByteArray();
+ } catch (IOException | ClassCastException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java
index 2e0a0c7e..b7cf1920 100644
--- a/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/GroupBanTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.GroupBanTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
@@ -15,20 +14,17 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class GroupBanTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int REASON_SIZE_LENGTH = INT_LENGTH;
private static final int TTL_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH + TTL_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH + TTL_LENGTH;
protected static final TransactionLayout layout;
@@ -36,6 +32,7 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.GROUP_BAN.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group admin's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -50,6 +47,10 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -68,15 +69,13 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new GroupBanTransactionData(adminPublicKey, groupId, offender, reason, timeToLive, fee, timestamp, reference, signature);
+ return new GroupBanTransactionData(timestamp, txGroupId, reference, adminPublicKey, groupId, offender, reason, timeToLive, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
GroupBanTransactionData groupBanTransactionData = (GroupBanTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupBanTransactionData.getReason());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(groupBanTransactionData.getReason());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -85,14 +84,14 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(groupBanTransactionData.getType().value));
- bytes.write(Longs.toByteArray(groupBanTransactionData.getTimestamp()));
- bytes.write(groupBanTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(groupBanTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(groupBanTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, groupBanTransactionData.getOffender());
+
Serialization.serializeSizedString(bytes, groupBanTransactionData.getReason());
+
bytes.write(Ints.toByteArray(groupBanTransactionData.getTimeToLive()));
Serialization.serializeBigDecimal(bytes, groupBanTransactionData.getFee());
@@ -106,27 +105,4 @@ public class GroupBanTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- GroupBanTransactionData groupBanTransactionData = (GroupBanTransactionData) transactionData;
-
- byte[] adminPublicKey = groupBanTransactionData.getAdminPublicKey();
-
- json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
- json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
-
- json.put("groupId", groupBanTransactionData.getGroupId());
- json.put("offender", groupBanTransactionData.getOffender());
- json.put("reason", groupBanTransactionData.getReason());
- json.put("timeToLive", groupBanTransactionData.getTimeToLive());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java
index 98c2df43..87677553 100644
--- a/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/GroupInviteTransactionTransformer.java
@@ -5,27 +5,23 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class GroupInviteTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int INVITEE_LENGTH = ADDRESS_LENGTH;
private static final int TTL_LENGTH = INT_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + INVITEE_LENGTH + TTL_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + INVITEE_LENGTH + TTL_LENGTH;
protected static final TransactionLayout layout;
@@ -33,6 +29,7 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.GROUP_INVITE.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group admin's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -45,6 +42,10 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -61,11 +62,11 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new GroupInviteTransactionData(adminPublicKey, groupId, invitee, timeToLive, fee, timestamp, reference, signature);
+ return new GroupInviteTransactionData(timestamp, txGroupId, reference, adminPublicKey, groupId, invitee, timeToLive, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -74,13 +75,12 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(groupInviteTransactionData.getType().value));
- bytes.write(Longs.toByteArray(groupInviteTransactionData.getTimestamp()));
- bytes.write(groupInviteTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(groupInviteTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(groupInviteTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, groupInviteTransactionData.getInvitee());
+
bytes.write(Ints.toByteArray(groupInviteTransactionData.getTimeToLive()));
Serialization.serializeBigDecimal(bytes, groupInviteTransactionData.getFee());
@@ -94,26 +94,4 @@ public class GroupInviteTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- GroupInviteTransactionData groupInviteTransactionData = (GroupInviteTransactionData) transactionData;
-
- byte[] adminPublicKey = groupInviteTransactionData.getAdminPublicKey();
-
- json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
- json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
-
- json.put("groupId", groupInviteTransactionData.getGroupId());
- json.put("invitee", groupInviteTransactionData.getInvitee());
- json.put("timeToLive", groupInviteTransactionData.getTimeToLive());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java
index a2dd9bfe..db6241c6 100644
--- a/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/GroupKickTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.GroupKickTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
@@ -15,19 +14,16 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class GroupKickTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int ADMIN_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
private static final int REASON_SIZE_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + ADMIN_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + MEMBER_LENGTH + REASON_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -35,6 +31,7 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.GROUP_KICK.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group admin's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -48,6 +45,10 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -64,15 +65,13 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new GroupKickTransactionData(adminPublicKey, groupId, member, reason, fee, timestamp, reference, signature);
+ return new GroupKickTransactionData(timestamp, txGroupId, reference, adminPublicKey, groupId, member, reason, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
GroupKickTransactionData groupKickTransactionData = (GroupKickTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(groupKickTransactionData.getReason());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(groupKickTransactionData.getReason());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -81,13 +80,12 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(groupKickTransactionData.getType().value));
- bytes.write(Longs.toByteArray(groupKickTransactionData.getTimestamp()));
- bytes.write(groupKickTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(groupKickTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(groupKickTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, groupKickTransactionData.getMember());
+
Serialization.serializeSizedString(bytes, groupKickTransactionData.getReason());
Serialization.serializeBigDecimal(bytes, groupKickTransactionData.getFee());
@@ -101,26 +99,4 @@ public class GroupKickTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- GroupKickTransactionData groupKickTransactionData = (GroupKickTransactionData) transactionData;
-
- byte[] adminPublicKey = groupKickTransactionData.getAdminPublicKey();
-
- json.put("admin", PublicKeyAccount.getAddress(adminPublicKey));
- json.put("adminPublicKey", HashCode.fromBytes(adminPublicKey).toString());
-
- json.put("groupId", groupKickTransactionData.getGroupId());
- json.put("member", groupKickTransactionData.getMember());
- json.put("reason", groupKickTransactionData.getReason());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java
index 6da7819f..49644147 100644
--- a/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/IssueAssetTransactionTransformer.java
@@ -6,8 +6,6 @@ import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.util.Arrays;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
import org.qora.block.BlockChain;
import org.qora.data.transaction.IssueAssetTransactionData;
import org.qora.data.transaction.TransactionData;
@@ -17,14 +15,11 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
public class IssueAssetTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int ISSUER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
@@ -32,8 +27,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
private static final int IS_DIVISIBLE_LENGTH = BOOLEAN_LENGTH;
private static final int ASSET_REFERENCE_LENGTH = REFERENCE_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + ISSUER_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH
- + QUANTITY_LENGTH + IS_DIVISIBLE_LENGTH;
+ private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DESCRIPTION_SIZE_LENGTH + QUANTITY_LENGTH + IS_DIVISIBLE_LENGTH;
protected static final TransactionLayout layout;
@@ -41,6 +35,7 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.ISSUE_ASSET.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("asset issuer's public key", TransformationType.PUBLIC_KEY);
layout.add("asset owner", TransformationType.ADDRESS);
@@ -57,6 +52,10 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -82,13 +81,14 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new IssueAssetTransactionData(issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee, timestamp, reference, signature);
+ return new IssueAssetTransactionData(timestamp, txGroupId, reference, issuerPublicKey, owner, assetName, description, quantity, isDivisible, fee,
+ signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getAssetName())
+ int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(issueAssetTransactionData.getAssetName())
+ Utf8.encodedLength(issueAssetTransactionData.getDescription());
// In v1, IssueAssetTransaction uses Asset.toBytes which also serializes reference.
@@ -104,15 +104,12 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(issueAssetTransactionData.getType().value));
- bytes.write(Longs.toByteArray(issueAssetTransactionData.getTimestamp()));
- bytes.write(issueAssetTransactionData.getReference());
-
- bytes.write(issueAssetTransactionData.getIssuerPublicKey());
+ transformCommonBytes(transactionData, bytes);
Serialization.serializeAddress(bytes, issueAssetTransactionData.getOwner());
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getAssetName());
+
Serialization.serializeSizedString(bytes, issueAssetTransactionData.getDescription());
bytes.write(Longs.toByteArray(issueAssetTransactionData.getQuantity()));
@@ -161,27 +158,4 @@ public class IssueAssetTransactionTransformer extends TransactionTransformer {
return bytes;
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- IssueAssetTransactionData issueAssetTransactionData = (IssueAssetTransactionData) transactionData;
-
- byte[] issuerPublicKey = issueAssetTransactionData.getIssuerPublicKey();
-
- json.put("issuer", PublicKeyAccount.getAddress(issuerPublicKey));
- json.put("issuerPublicKey", HashCode.fromBytes(issuerPublicKey).toString());
- json.put("owner", issueAssetTransactionData.getOwner());
- json.put("assetName", issueAssetTransactionData.getAssetName());
- json.put("description", issueAssetTransactionData.getDescription());
- json.put("quantity", issueAssetTransactionData.getQuantity());
- json.put("isDivisible", issueAssetTransactionData.getIsDivisible());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java
index 26bab418..5728eadc 100644
--- a/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/JoinGroupTransactionTransformer.java
@@ -5,25 +5,21 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class JoinGroupTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int JOINER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + GROUPID_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH;
protected static final TransactionLayout layout;
@@ -31,6 +27,7 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.JOIN_GROUP.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("joiner's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -41,6 +38,10 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -53,11 +54,11 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new JoinGroupTransactionData(joinerPublicKey, groupId, fee, timestamp, reference, signature);
+ return new JoinGroupTransactionData(timestamp, txGroupId, reference, joinerPublicKey, groupId, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -66,11 +67,8 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(joinGroupTransactionData.getType().value));
- bytes.write(Longs.toByteArray(joinGroupTransactionData.getTimestamp()));
- bytes.write(joinGroupTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(joinGroupTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(joinGroupTransactionData.getGroupId()));
Serialization.serializeBigDecimal(bytes, joinGroupTransactionData.getFee());
@@ -84,24 +82,4 @@ public class JoinGroupTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- JoinGroupTransactionData joinGroupTransactionData = (JoinGroupTransactionData) transactionData;
-
- byte[] joinerPublicKey = joinGroupTransactionData.getJoinerPublicKey();
-
- json.put("joiner", PublicKeyAccount.getAddress(joinerPublicKey));
- json.put("joinerPublicKey", HashCode.fromBytes(joinerPublicKey).toString());
-
- json.put("groupId", joinGroupTransactionData.getGroupId());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java
index 77c4634b..3bee73f0 100644
--- a/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/LeaveGroupTransactionTransformer.java
@@ -5,25 +5,21 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class LeaveGroupTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int JOINER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + JOINER_LENGTH + GROUPID_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH;
protected static final TransactionLayout layout;
@@ -31,6 +27,7 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.LEAVE_GROUP.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("leaver's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -41,6 +38,10 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -53,11 +54,11 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new LeaveGroupTransactionData(leaverPublicKey, groupId, fee, timestamp, reference, signature);
+ return new LeaveGroupTransactionData(timestamp, txGroupId, reference, leaverPublicKey, groupId, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -66,11 +67,8 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(leaveGroupTransactionData.getType().value));
- bytes.write(Longs.toByteArray(leaveGroupTransactionData.getTimestamp()));
- bytes.write(leaveGroupTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(leaveGroupTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(leaveGroupTransactionData.getGroupId()));
Serialization.serializeBigDecimal(bytes, leaveGroupTransactionData.getFee());
@@ -84,24 +82,4 @@ public class LeaveGroupTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- LeaveGroupTransactionData leaveGroupTransactionData = (LeaveGroupTransactionData) transactionData;
-
- byte[] leaverPublicKey = leaveGroupTransactionData.getLeaverPublicKey();
-
- json.put("leaver", PublicKeyAccount.getAddress(leaverPublicKey));
- json.put("leaverPublicKey", HashCode.fromBytes(leaverPublicKey).toString());
-
- json.put("groupId", leaveGroupTransactionData.getGroupId());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java
index 7f6d06ca..d8f43e2f 100644
--- a/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/MessageTransactionTransformer.java
@@ -4,11 +4,9 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import java.nio.charset.Charset;
-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.MessageTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.transaction.MessageTransaction;
@@ -16,14 +14,12 @@ import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
public class MessageTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int SENDER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH;
private static final int AMOUNT_LENGTH = BIG_DECIMAL_LENGTH;
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
@@ -31,10 +27,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
private static final int IS_TEXT_LENGTH = BOOLEAN_LENGTH;
private static final int IS_ENCRYPTED_LENGTH = BOOLEAN_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH_V1 = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH + DATA_SIZE_LENGTH
- + IS_TEXT_LENGTH + IS_ENCRYPTED_LENGTH;
- 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;
+ private static final int EXTRAS_LENGTH = RECIPIENT_LENGTH + AMOUNT_LENGTH + DATA_SIZE_LENGTH + IS_TEXT_LENGTH + IS_ENCRYPTED_LENGTH;
protected static final TransactionLayout layout;
@@ -42,6 +35,7 @@ public class MessageTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.MESSAGE.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("sender's public key", TransformationType.PUBLIC_KEY);
layout.add("recipient", TransformationType.ADDRESS);
@@ -60,6 +54,10 @@ public class MessageTransactionTransformer extends TransactionTransformer {
int version = MessageTransaction.getVersionByTimestamp(timestamp);
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -92,17 +90,20 @@ public class MessageTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new MessageTransactionData(version, senderPublicKey, recipient, assetId, amount, data, isText, isEncrypted, fee, timestamp, reference,
+ return new MessageTransactionData(timestamp, txGroupId, reference, senderPublicKey, version, recipient, assetId, amount, data, isText, isEncrypted, fee,
signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
MessageTransactionData messageTransactionData = (MessageTransactionData) transactionData;
- if (messageTransactionData.getVersion() == 1)
- return TYPE_LENGTH + TYPELESS_DATALESS_LENGTH_V1 + messageTransactionData.getData().length;
- else
- return TYPE_LENGTH + TYPELESS_DATALESS_LENGTH_V3 + messageTransactionData.getData().length;
+ int dataLength = getBaseLength(transactionData) + EXTRAS_LENGTH;
+
+ // V3+ has assetID for amount
+ if (messageTransactionData.getVersion() != 1)
+ dataLength += ASSET_ID_LENGTH;
+
+ return dataLength;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -111,20 +112,21 @@ public class MessageTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(messageTransactionData.getType().value));
- bytes.write(Longs.toByteArray(messageTransactionData.getTimestamp()));
- bytes.write(messageTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(messageTransactionData.getSenderPublicKey());
Serialization.serializeAddress(bytes, messageTransactionData.getRecipient());
if (messageTransactionData.getVersion() != 1)
bytes.write(Longs.toByteArray(messageTransactionData.getAssetId()));
Serialization.serializeBigDecimal(bytes, messageTransactionData.getAmount());
+
bytes.write(Ints.toByteArray(messageTransactionData.getData().length));
+
bytes.write(messageTransactionData.getData());
+
bytes.write((byte) (messageTransactionData.getIsEncrypted() ? 1 : 0));
+
bytes.write((byte) (messageTransactionData.getIsText() ? 1 : 0));
Serialization.serializeBigDecimal(bytes, messageTransactionData.getFee());
@@ -138,34 +140,4 @@ public class MessageTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- MessageTransactionData messageTransactionData = (MessageTransactionData) transactionData;
-
- byte[] senderPublicKey = messageTransactionData.getSenderPublicKey();
-
- json.put("version", messageTransactionData.getVersion());
- json.put("sender", PublicKeyAccount.getAddress(senderPublicKey));
- json.put("senderPublicKey", HashCode.fromBytes(senderPublicKey).toString());
- json.put("recipient", messageTransactionData.getRecipient());
- json.put("amount", messageTransactionData.getAmount().toPlainString());
- json.put("assetId", messageTransactionData.getAssetId());
- json.put("isText", messageTransactionData.getIsText());
- json.put("isEncrypted", messageTransactionData.getIsEncrypted());
-
- // We can only show plain text as unencoded
- if (messageTransactionData.getIsText() && !messageTransactionData.getIsEncrypted())
- json.put("data", new String(messageTransactionData.getData(), Charset.forName("UTF-8")));
- else
- json.put("data", HashCode.fromBytes(messageTransactionData.getData()).toString());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java
index 3b6c29bb..26ab08b1 100644
--- a/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/MultiPaymentTransactionTransformer.java
@@ -8,9 +8,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import org.json.simple.JSONArray;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
import org.qora.block.BlockChain;
import org.qora.data.PaymentData;
import org.qora.data.transaction.MultiPaymentTransactionData;
@@ -20,17 +17,14 @@ import org.qora.transform.PaymentTransformer;
import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class MultiPaymentTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int SENDER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int PAYMENTS_COUNT_LENGTH = INT_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + PAYMENTS_COUNT_LENGTH;
+ private static final int EXTRAS_LENGTH = PAYMENTS_COUNT_LENGTH;
protected static final TransactionLayout layout;
@@ -38,6 +32,7 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.MULTI_PAYMENT.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("sender's public key", TransformationType.PUBLIC_KEY);
layout.add("number of payments", TransformationType.INT);
@@ -51,6 +46,10 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -67,13 +66,13 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new MultiPaymentTransactionData(senderPublicKey, payments, fee, timestamp, reference, signature);
+ return new MultiPaymentTransactionData(timestamp, txGroupId, reference, senderPublicKey, payments, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
MultiPaymentTransactionData multiPaymentTransactionData = (MultiPaymentTransactionData) transactionData;
- return TYPE_LENGTH + TYPELESS_LENGTH + multiPaymentTransactionData.getPayments().size() * PaymentTransformer.getDataLength();
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + multiPaymentTransactionData.getPayments().size() * PaymentTransformer.getDataLength();
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -82,11 +81,7 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(multiPaymentTransactionData.getType().value));
- bytes.write(Longs.toByteArray(multiPaymentTransactionData.getTimestamp()));
- bytes.write(multiPaymentTransactionData.getReference());
-
- bytes.write(multiPaymentTransactionData.getSenderPublicKey());
+ transformCommonBytes(transactionData, bytes);
List payments = multiPaymentTransactionData.getPayments();
bytes.write(Ints.toByteArray(payments.size()));
@@ -128,30 +123,4 @@ public class MultiPaymentTransactionTransformer extends TransactionTransformer {
return Arrays.copyOfRange(bytes, v1Start, bytes.length);
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- MultiPaymentTransactionData multiPaymentTransactionData = (MultiPaymentTransactionData) transactionData;
-
- byte[] senderPublicKey = multiPaymentTransactionData.getSenderPublicKey();
-
- json.put("sender", PublicKeyAccount.getAddress(senderPublicKey));
- json.put("senderPublicKey", HashCode.fromBytes(senderPublicKey).toString());
-
- List payments = multiPaymentTransactionData.getPayments();
- JSONArray paymentsJson = new JSONArray();
-
- for (PaymentData paymentData : payments)
- paymentsJson.add(PaymentTransformer.toJSON(paymentData));
-
- json.put("payments", paymentsJson);
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java
index 636ad910..a3ca39b5 100644
--- a/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/PaymentTransactionTransformer.java
@@ -5,26 +5,20 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
-
public class PaymentTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int SENDER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH;
private static final int AMOUNT_LENGTH = BIG_DECIMAL_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + AMOUNT_LENGTH;
+ private static final int EXTRAS_LENGTH = RECIPIENT_LENGTH + AMOUNT_LENGTH;
protected static final TransactionLayout layout;
@@ -32,6 +26,7 @@ public class PaymentTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.PAYMENT.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("sender's public key", TransformationType.PUBLIC_KEY);
layout.add("recipient", TransformationType.ADDRESS);
@@ -43,6 +38,10 @@ public class PaymentTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -57,11 +56,11 @@ public class PaymentTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new PaymentTransactionData(senderPublicKey, recipient, amount, fee, timestamp, reference, signature);
+ return new PaymentTransactionData(timestamp, txGroupId, reference, senderPublicKey, recipient, amount, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -70,12 +69,10 @@ public class PaymentTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(paymentTransactionData.getType().value));
- bytes.write(Longs.toByteArray(paymentTransactionData.getTimestamp()));
- bytes.write(paymentTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(paymentTransactionData.getSenderPublicKey());
Serialization.serializeAddress(bytes, paymentTransactionData.getRecipient());
+
Serialization.serializeBigDecimal(bytes, paymentTransactionData.getAmount());
Serialization.serializeBigDecimal(bytes, paymentTransactionData.getFee());
@@ -89,24 +86,4 @@ public class PaymentTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- PaymentTransactionData paymentTransactionData = (PaymentTransactionData) transactionData;
-
- byte[] senderPublicKey = paymentTransactionData.getSenderPublicKey();
-
- json.put("sender", PublicKeyAccount.getAddress(senderPublicKey));
- json.put("senderPublicKey", HashCode.fromBytes(senderPublicKey).toString());
- json.put("recipient", paymentTransactionData.getRecipient());
- json.put("amount", paymentTransactionData.getAmount().toPlainString());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java
index 9cdf4c91..39aad278 100644
--- a/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/RegisterNameTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.RegisterNameTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.naming.Name;
@@ -15,19 +14,15 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class RegisterNameTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int REGISTRANT_LENGTH = PUBLIC_KEY_LENGTH;
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + REGISTRANT_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DATA_SIZE_LENGTH;
+ private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DATA_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -35,6 +30,7 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.REGISTER_NAME.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("name registrant's public key", TransformationType.PUBLIC_KEY);
layout.add("name owner", TransformationType.ADDRESS);
@@ -49,6 +45,10 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -65,16 +65,14 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new RegisterNameTransactionData(registrantPublicKey, owner, name, data, fee, timestamp, reference, signature);
+ return new RegisterNameTransactionData(timestamp, txGroupId, reference, registrantPublicKey, owner, name, data, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
RegisterNameTransactionData registerNameTransactionData = (RegisterNameTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(registerNameTransactionData.getName())
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(registerNameTransactionData.getName())
+ Utf8.encodedLength(registerNameTransactionData.getData());
-
- return dataLength;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -83,13 +81,12 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(registerNameTransactionData.getType().value));
- bytes.write(Longs.toByteArray(registerNameTransactionData.getTimestamp()));
- bytes.write(registerNameTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(registerNameTransactionData.getRegistrantPublicKey());
Serialization.serializeAddress(bytes, registerNameTransactionData.getOwner());
+
Serialization.serializeSizedString(bytes, registerNameTransactionData.getName());
+
Serialization.serializeSizedString(bytes, registerNameTransactionData.getData());
Serialization.serializeBigDecimal(bytes, registerNameTransactionData.getFee());
@@ -103,26 +100,4 @@ public class RegisterNameTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- RegisterNameTransactionData registerNameTransactionData = (RegisterNameTransactionData) transactionData;
-
- byte[] registrantPublicKey = registerNameTransactionData.getRegistrantPublicKey();
-
- json.put("registrant", PublicKeyAccount.getAddress(registrantPublicKey));
- json.put("registrantPublicKey", HashCode.fromBytes(registrantPublicKey).toString());
-
- json.put("owner", registerNameTransactionData.getOwner());
- json.put("name", registerNameTransactionData.getName());
- json.put("data", registerNameTransactionData.getData());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java
index 2d265b89..99fd991f 100644
--- a/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/RemoveGroupAdminTransactionTransformer.java
@@ -5,26 +5,22 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class RemoveGroupAdminTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int MEMBER_LENGTH = ADDRESS_LENGTH;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + GROUPID_LENGTH + MEMBER_LENGTH;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + MEMBER_LENGTH;
protected static final TransactionLayout layout;
@@ -32,6 +28,7 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.REMOVE_GROUP_ADMIN.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group owner's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -43,6 +40,10 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -57,11 +58,11 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new RemoveGroupAdminTransactionData(ownerPublicKey, groupId, admin, fee, timestamp, reference, signature);
+ return new RemoveGroupAdminTransactionData(timestamp, txGroupId, reference, ownerPublicKey, groupId, admin, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -70,12 +71,10 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(removeGroupAdminTransactionData.getType().value));
- bytes.write(Longs.toByteArray(removeGroupAdminTransactionData.getTimestamp()));
- bytes.write(removeGroupAdminTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(removeGroupAdminTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(removeGroupAdminTransactionData.getGroupId()));
+
Serialization.serializeAddress(bytes, removeGroupAdminTransactionData.getAdmin());
Serialization.serializeBigDecimal(bytes, removeGroupAdminTransactionData.getFee());
@@ -89,25 +88,4 @@ public class RemoveGroupAdminTransactionTransformer extends TransactionTransform
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- RemoveGroupAdminTransactionData removeGroupAdminTransactionData = (RemoveGroupAdminTransactionData) transactionData;
-
- byte[] ownerPublicKey = removeGroupAdminTransactionData.getOwnerPublicKey();
-
- json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
- json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
-
- json.put("groupId", removeGroupAdminTransactionData.getGroupId());
- json.put("admin", removeGroupAdminTransactionData.getAdmin());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java
index 66af7b53..63a0663a 100644
--- a/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/SellNameTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.SellNameTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.naming.Name;
@@ -15,18 +14,14 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class SellNameTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int AMOUNT_LENGTH = BIG_DECIMAL_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + AMOUNT_LENGTH;
+ private static final int EXTRAS_LENGTH = NAME_SIZE_LENGTH + AMOUNT_LENGTH;
protected static final TransactionLayout layout;
@@ -34,6 +29,7 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.SELL_NAME.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("name owner's public key", TransformationType.PUBLIC_KEY);
layout.add("name length", TransformationType.INT);
@@ -46,6 +42,10 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -60,15 +60,13 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new SellNameTransactionData(ownerPublicKey, name, amount, fee, timestamp, reference, signature);
+ return new SellNameTransactionData(timestamp, txGroupId, reference, ownerPublicKey, name, amount, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(sellNameTransactionData.getName());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(sellNameTransactionData.getName());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -77,12 +75,10 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(sellNameTransactionData.getType().value));
- bytes.write(Longs.toByteArray(sellNameTransactionData.getTimestamp()));
- bytes.write(sellNameTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(sellNameTransactionData.getOwnerPublicKey());
Serialization.serializeSizedString(bytes, sellNameTransactionData.getName());
+
Serialization.serializeBigDecimal(bytes, sellNameTransactionData.getAmount());
Serialization.serializeBigDecimal(bytes, sellNameTransactionData.getFee());
@@ -96,25 +92,4 @@ public class SellNameTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- SellNameTransactionData sellNameTransactionData = (SellNameTransactionData) transactionData;
-
- byte[] ownerPublicKey = sellNameTransactionData.getOwnerPublicKey();
-
- json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
- json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
-
- json.put("name", sellNameTransactionData.getName());
- json.put("amount", sellNameTransactionData.getAmount().toPlainString());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/SetGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/SetGroupTransactionTransformer.java
new file mode 100644
index 00000000..1faf1c29
--- /dev/null
+++ b/src/main/java/org/qora/transform/transaction/SetGroupTransactionTransformer.java
@@ -0,0 +1,85 @@
+package org.qora.transform.transaction;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.nio.ByteBuffer;
+
+import org.qora.block.BlockChain;
+import org.qora.data.transaction.SetGroupTransactionData;
+import org.qora.data.transaction.TransactionData;
+import org.qora.transaction.Transaction.TransactionType;
+import org.qora.transform.TransformationException;
+import org.qora.utils.Serialization;
+
+import com.google.common.primitives.Ints;
+
+public class SetGroupTransactionTransformer extends TransactionTransformer {
+
+ // Property lengths
+ private static final int GROUPID_LENGTH = SIGNATURE_LENGTH;
+
+ private static final int EXTRAS_LENGTH = GROUPID_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("transaction's groupID", TransformationType.INT);
+ layout.add("reference", TransformationType.SIGNATURE);
+ layout.add("account's public key", TransformationType.PUBLIC_KEY);
+ layout.add("account's new default groupID", TransformationType.INT);
+ layout.add("fee", TransformationType.AMOUNT);
+ layout.add("signature", TransformationType.SIGNATURE);
+ }
+
+ public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
+ long timestamp = byteBuffer.getLong();
+
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
+ byte[] reference = new byte[REFERENCE_LENGTH];
+ byteBuffer.get(reference);
+
+ byte[] creatorPublicKey = Serialization.deserializePublicKey(byteBuffer);
+
+ int defaultGroupId = byteBuffer.getInt();
+
+ BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
+
+ byte[] signature = new byte[SIGNATURE_LENGTH];
+ byteBuffer.get(signature);
+
+ return new SetGroupTransactionData(timestamp, txGroupId, reference, creatorPublicKey, defaultGroupId, fee, signature);
+ }
+
+ public static int getDataLength(TransactionData transactionData) throws TransformationException {
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
+ }
+
+ public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
+ try {
+ SetGroupTransactionData setGroupTransactionData = (SetGroupTransactionData) transactionData;
+
+ ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+
+ transformCommonBytes(transactionData, bytes);
+
+ bytes.write(Ints.toByteArray(setGroupTransactionData.getDefaultGroupId()));
+
+ Serialization.serializeBigDecimal(bytes, setGroupTransactionData.getFee());
+
+ if (setGroupTransactionData.getSignature() != null)
+ bytes.write(setGroupTransactionData.getSignature());
+
+ return bytes.toByteArray();
+ } catch (IOException | ClassCastException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+}
diff --git a/src/main/java/org/qora/transform/transaction/TransactionTransformer.java b/src/main/java/org/qora/transform/transaction/TransactionTransformer.java
index 8d079762..147572af 100644
--- a/src/main/java/org/qora/transform/transaction/TransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/TransactionTransformer.java
@@ -1,5 +1,7 @@
package org.qora.transform.transaction;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -15,25 +17,26 @@ import javax.xml.bind.annotation.XmlElement;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
-import org.json.simple.JSONObject;
import org.qora.account.PrivateKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.TransactionData;
import org.qora.transaction.Transaction;
import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException;
import org.qora.transform.Transformer;
-import org.qora.utils.Base58;
import com.google.common.hash.HashCode;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
public abstract class TransactionTransformer extends Transformer {
private static final Logger LOGGER = LogManager.getLogger(TransactionTransformer.class);
protected static final int TYPE_LENGTH = INT_LENGTH;
+ protected static final int GROUPID_LENGTH = INT_LENGTH;
protected static final int REFERENCE_LENGTH = SIGNATURE_LENGTH;
protected static final int FEE_LENGTH = BIG_DECIMAL_LENGTH;
- protected static final int BASE_TYPELESS_LENGTH = TIMESTAMP_LENGTH + REFERENCE_LENGTH + FEE_LENGTH + SIGNATURE_LENGTH;
/** Description of one component of raw transaction layout */
public enum TransformationType {
@@ -47,7 +50,8 @@ public abstract class TransactionTransformer extends Transformer {
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);
+ BOOLEAN("0 for false, anything else for true", 1),
+ BYTE("byte", 1);
public final String description;
public final Integer length;
@@ -109,7 +113,6 @@ public abstract class TransactionTransformer extends Transformer {
public Method getDataLengthMethod;
public Method toBytesMethod;
public Method toBytesForSigningImplMethod;
- public Method toJSONMethod;
}
/** Cache of transformer subclass info, keyed by transaction type */
@@ -166,12 +169,6 @@ public abstract class TransactionTransformer extends Transformer {
txType.name()));
}
- try {
- subclassInfo.toJSONMethod = subclassInfo.clazz.getDeclaredMethod("toJSON", TransactionData.class);
- } catch (IllegalArgumentException | SecurityException | NoSuchMethodException e) {
- LOGGER.debug(String.format("TransactionTransformer subclass's \"toJSON\" method not found for transaction type \"%s\"", txType.name()));
- }
-
subclassInfos[txType.value] = subclassInfo;
}
@@ -218,6 +215,16 @@ public abstract class TransactionTransformer extends Transformer {
}
}
+ protected static int getBaseLength(TransactionData transactionData) {
+ // All transactions have at least txType, timestamp, maybe txGroupId, tx creator's public key and finally signature (on the end)
+ int baseLength = TYPE_LENGTH + TIMESTAMP_LENGTH + PUBLIC_KEY_LENGTH + SIGNATURE_LENGTH;
+
+ if (transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp())
+ baseLength += GROUPID_LENGTH;
+
+ return baseLength;
+ }
+
public static int getDataLength(TransactionData transactionData) throws TransformationException {
TransactionType type = transactionData.getType();
@@ -280,34 +287,24 @@ public abstract class TransactionTransformer extends Transformer {
}
}
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- TransactionType type = transactionData.getType();
+ protected static void transformCommonBytes(TransactionData transactionData, ByteArrayOutputStream bytes) throws IOException {
+ boolean v2 = transactionData.getTimestamp() >= BlockChain.getInstance().getQoraV2Timestamp();
- try {
- Method method = subclassInfos[type.value].toJSONMethod;
- return (JSONObject) method.invoke(null, transactionData);
- } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- throw new TransformationException("Internal error with transaction type [" + type.value + "] during conversion to JSON");
- }
- }
+ // Transaction type
+ bytes.write(Ints.toByteArray(transactionData.getType().value));
- @SuppressWarnings("unchecked")
- static JSONObject getBaseJSON(TransactionData transaction) {
- JSONObject json = new JSONObject();
+ // Timestamp
+ bytes.write(Longs.toByteArray(transactionData.getTimestamp()));
- json.put("type", transaction.getType().value);
- json.put("fee", transaction.getFee().toPlainString());
- json.put("timestamp", transaction.getTimestamp());
- json.put("signature", Base58.encode(transaction.getSignature()));
+ if (v2)
+ // Transaction's groupID
+ bytes.write(Ints.toByteArray(transactionData.getTxGroupId()));
- byte[] reference = transaction.getReference();
- if (reference != null)
- json.put("reference", Base58.encode(reference));
+ // Reference
+ bytes.write(transactionData.getReference());
- // XXX Can't do this as it requires database access:
- // json.put("confirmations", RepositoryManager.getTransactionRepository.getConfirmations(transaction));
-
- return json;
+ // Creator public key
+ bytes.write(transactionData.getCreatorPublicKey());
}
}
diff --git a/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java
index d6b0d650..720f0ed8 100644
--- a/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/TransferAssetTransactionTransformer.java
@@ -5,27 +5,23 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
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;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
import com.google.common.primitives.Longs;
public class TransferAssetTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int SENDER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int RECIPIENT_LENGTH = ADDRESS_LENGTH;
private static final int ASSET_ID_LENGTH = LONG_LENGTH;
private static final int AMOUNT_LENGTH = 12;
- private static final int TYPELESS_LENGTH = BASE_TYPELESS_LENGTH + SENDER_LENGTH + RECIPIENT_LENGTH + ASSET_ID_LENGTH + AMOUNT_LENGTH;
+ private static final int EXTRAS_LENGTH = RECIPIENT_LENGTH + ASSET_ID_LENGTH + AMOUNT_LENGTH;
protected static final TransactionLayout layout;
@@ -33,6 +29,7 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.TRANSFER_ASSET.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("asset owner's public key", TransformationType.PUBLIC_KEY);
layout.add("asset's new owner", TransformationType.ADDRESS);
@@ -44,6 +41,10 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -60,11 +61,11 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new TransferAssetTransactionData(senderPublicKey, recipient, amount, assetId, fee, timestamp, reference, signature);
+ return new TransferAssetTransactionData(timestamp, txGroupId, reference, senderPublicKey, recipient, amount, assetId, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
- return TYPE_LENGTH + TYPELESS_LENGTH;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -73,13 +74,12 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(transferAssetTransactionData.getType().value));
- bytes.write(Longs.toByteArray(transferAssetTransactionData.getTimestamp()));
- bytes.write(transferAssetTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(transferAssetTransactionData.getSenderPublicKey());
Serialization.serializeAddress(bytes, transferAssetTransactionData.getRecipient());
+
bytes.write(Longs.toByteArray(transferAssetTransactionData.getAssetId()));
+
Serialization.serializeBigDecimal(bytes, transferAssetTransactionData.getAmount(), AMOUNT_LENGTH);
Serialization.serializeBigDecimal(bytes, transferAssetTransactionData.getFee());
@@ -93,30 +93,4 @@ public class TransferAssetTransactionTransformer extends TransactionTransformer
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- TransferAssetTransactionData transferAssetTransactionData = (TransferAssetTransactionData) transactionData;
-
- byte[] senderPublicKey = transferAssetTransactionData.getSenderPublicKey();
-
- json.put("sender", PublicKeyAccount.getAddress(senderPublicKey));
- json.put("senderPublicKey", HashCode.fromBytes(senderPublicKey).toString());
- json.put("recipient", transferAssetTransactionData.getRecipient());
-
- // For gen1 support:
- json.put("asset", transferAssetTransactionData.getAssetId());
- // Gen2 version:
- json.put("assetId", transferAssetTransactionData.getAssetId());
-
- json.put("amount", transferAssetTransactionData.getAmount().toPlainString());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java
index 5d63f331..ab9490e3 100644
--- a/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/UpdateGroupTransactionTransformer.java
@@ -5,31 +5,29 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.UpdateGroupTransactionData;
import org.qora.data.transaction.TransactionData;
import org.qora.group.Group;
+import org.qora.group.Group.ApprovalThreshold;
import org.qora.transaction.Transaction.TransactionType;
import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class UpdateGroupTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int OWNER_LENGTH = PUBLIC_KEY_LENGTH;
private static final int GROUPID_LENGTH = INT_LENGTH;
private static final int NEW_OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NEW_DESCRIPTION_SIZE_LENGTH = INT_LENGTH;
private static final int NEW_IS_OPEN_LENGTH = BOOLEAN_LENGTH;
+ private static final int NEW_APPROVAL_THRESHOLD_LENGTH = BYTE_LENGTH;
- 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;
+ private static final int EXTRAS_LENGTH = GROUPID_LENGTH + NEW_OWNER_LENGTH + NEW_DESCRIPTION_SIZE_LENGTH + NEW_IS_OPEN_LENGTH
+ + NEW_APPROVAL_THRESHOLD_LENGTH;
protected static final TransactionLayout layout;
@@ -37,6 +35,7 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.UPDATE_GROUP.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("group owner's public key", TransformationType.PUBLIC_KEY);
layout.add("group ID", TransformationType.INT);
@@ -44,6 +43,7 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
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("new group transaction approval threshold", TransformationType.BYTE);
layout.add("fee", TransformationType.AMOUNT);
layout.add("signature", TransformationType.SIGNATURE);
}
@@ -51,6 +51,10 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -64,20 +68,21 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
boolean newIsOpen = byteBuffer.get() != 0;
+ ApprovalThreshold newApprovalThreshold = ApprovalThreshold.valueOf(byteBuffer.get());
+
BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer);
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new UpdateGroupTransactionData(ownerPublicKey, groupId, newOwner, newDescription, newIsOpen, fee, timestamp, reference, signature);
+ return new UpdateGroupTransactionData(timestamp, txGroupId, reference, ownerPublicKey, groupId, newOwner, newDescription, newIsOpen,
+ newApprovalThreshold, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
UpdateGroupTransactionData updateGroupTransactionData = (UpdateGroupTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(updateGroupTransactionData.getNewDescription());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(updateGroupTransactionData.getNewDescription());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -86,18 +91,18 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(updateGroupTransactionData.getType().value));
- bytes.write(Longs.toByteArray(updateGroupTransactionData.getTimestamp()));
- bytes.write(updateGroupTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(updateGroupTransactionData.getCreatorPublicKey());
bytes.write(Ints.toByteArray(updateGroupTransactionData.getGroupId()));
Serialization.serializeAddress(bytes, updateGroupTransactionData.getNewOwner());
+
Serialization.serializeSizedString(bytes, updateGroupTransactionData.getNewDescription());
bytes.write((byte) (updateGroupTransactionData.getNewIsOpen() ? 1 : 0));
+ bytes.write((byte) updateGroupTransactionData.getNewApprovalThreshold().value);
+
Serialization.serializeBigDecimal(bytes, updateGroupTransactionData.getFee());
if (updateGroupTransactionData.getSignature() != null)
@@ -109,27 +114,4 @@ public class UpdateGroupTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- UpdateGroupTransactionData updateGroupTransactionData = (UpdateGroupTransactionData) transactionData;
-
- byte[] ownerPublicKey = updateGroupTransactionData.getOwnerPublicKey();
-
- json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
- json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
-
- json.put("groupId", updateGroupTransactionData.getGroupId());
- json.put("newOwner", updateGroupTransactionData.getNewOwner());
- json.put("newDescription", updateGroupTransactionData.getNewDescription());
- json.put("newIsOpen", updateGroupTransactionData.getNewIsOpen());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java
index 58beec5e..4db37fae 100644
--- a/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/UpdateNameTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.TransactionData;
import org.qora.data.transaction.UpdateNameTransactionData;
import org.qora.naming.Name;
@@ -15,19 +14,15 @@ import org.qora.transform.TransformationException;
import org.qora.utils.Serialization;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
-import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class UpdateNameTransactionTransformer extends TransactionTransformer {
// Property lengths
- private static final int REGISTRANT_LENGTH = PUBLIC_KEY_LENGTH;
private static final int OWNER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
private static final int DATA_SIZE_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + REGISTRANT_LENGTH + OWNER_LENGTH + NAME_SIZE_LENGTH + DATA_SIZE_LENGTH;
+ private static final int EXTRAS_LENGTH = OWNER_LENGTH + NAME_SIZE_LENGTH + DATA_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -35,6 +30,7 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.UPDATE_NAME.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("name owner's public key", TransformationType.PUBLIC_KEY);
layout.add("name's new owner", TransformationType.ADDRESS);
@@ -49,6 +45,10 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -65,16 +65,14 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new UpdateNameTransactionData(ownerPublicKey, newOwner, name, newData, fee, timestamp, reference, signature);
+ return new UpdateNameTransactionData(timestamp, txGroupId, reference, ownerPublicKey, newOwner, name, newData, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
UpdateNameTransactionData updateNameTransactionData = (UpdateNameTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(updateNameTransactionData.getName())
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(updateNameTransactionData.getName())
+ Utf8.encodedLength(updateNameTransactionData.getNewData());
-
- return dataLength;
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -83,13 +81,12 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(updateNameTransactionData.getType().value));
- bytes.write(Longs.toByteArray(updateNameTransactionData.getTimestamp()));
- bytes.write(updateNameTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
- bytes.write(updateNameTransactionData.getOwnerPublicKey());
Serialization.serializeAddress(bytes, updateNameTransactionData.getNewOwner());
+
Serialization.serializeSizedString(bytes, updateNameTransactionData.getName());
+
Serialization.serializeSizedString(bytes, updateNameTransactionData.getNewData());
Serialization.serializeBigDecimal(bytes, updateNameTransactionData.getFee());
@@ -103,26 +100,4 @@ public class UpdateNameTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- UpdateNameTransactionData updateNameTransactionData = (UpdateNameTransactionData) transactionData;
-
- byte[] ownerPublicKey = updateNameTransactionData.getOwnerPublicKey();
-
- json.put("owner", PublicKeyAccount.getAddress(ownerPublicKey));
- json.put("ownerPublicKey", HashCode.fromBytes(ownerPublicKey).toString());
-
- json.put("newOwner", updateNameTransactionData.getNewOwner());
- json.put("name", updateNameTransactionData.getName());
- json.put("newData", updateNameTransactionData.getNewData());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java
index 171f46a7..367d05b4 100644
--- a/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java
+++ b/src/main/java/org/qora/transform/transaction/VoteOnPollTransactionTransformer.java
@@ -5,8 +5,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.ByteBuffer;
-import org.json.simple.JSONObject;
-import org.qora.account.PublicKeyAccount;
+import org.qora.block.BlockChain;
import org.qora.data.transaction.TransactionData;
import org.qora.data.transaction.VoteOnPollTransactionData;
import org.qora.transaction.Transaction.TransactionType;
@@ -15,9 +14,7 @@ import org.qora.utils.Serialization;
import org.qora.voting.Poll;
import com.google.common.base.Utf8;
-import com.google.common.hash.HashCode;
import com.google.common.primitives.Ints;
-import com.google.common.primitives.Longs;
public class VoteOnPollTransactionTransformer extends TransactionTransformer {
@@ -25,7 +22,7 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
private static final int VOTER_LENGTH = ADDRESS_LENGTH;
private static final int NAME_SIZE_LENGTH = INT_LENGTH;
- private static final int TYPELESS_DATALESS_LENGTH = BASE_TYPELESS_LENGTH + VOTER_LENGTH + NAME_SIZE_LENGTH;
+ private static final int EXTRAS_LENGTH = VOTER_LENGTH + NAME_SIZE_LENGTH;
protected static final TransactionLayout layout;
@@ -33,6 +30,7 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
layout = new TransactionLayout();
layout.add("txType: " + TransactionType.VOTE_ON_POLL.valueString, TransformationType.INT);
layout.add("timestamp", TransformationType.TIMESTAMP);
+ layout.add("transaction's groupID", TransformationType.INT);
layout.add("reference", TransformationType.SIGNATURE);
layout.add("voter's public key", TransformationType.PUBLIC_KEY);
layout.add("poll name length", TransformationType.INT);
@@ -45,6 +43,10 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
public static TransactionData fromByteBuffer(ByteBuffer byteBuffer) throws TransformationException {
long timestamp = byteBuffer.getLong();
+ int txGroupId = 0;
+ if (timestamp >= BlockChain.getInstance().getQoraV2Timestamp())
+ txGroupId = byteBuffer.getInt();
+
byte[] reference = new byte[REFERENCE_LENGTH];
byteBuffer.get(reference);
@@ -61,15 +63,13 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
byte[] signature = new byte[SIGNATURE_LENGTH];
byteBuffer.get(signature);
- return new VoteOnPollTransactionData(voterPublicKey, pollName, optionIndex, fee, timestamp, reference, signature);
+ return new VoteOnPollTransactionData(timestamp, txGroupId, reference, voterPublicKey, pollName, optionIndex, fee, signature);
}
public static int getDataLength(TransactionData transactionData) throws TransformationException {
VoteOnPollTransactionData voteOnPollTransactionData = (VoteOnPollTransactionData) transactionData;
- int dataLength = TYPE_LENGTH + TYPELESS_DATALESS_LENGTH + Utf8.encodedLength(voteOnPollTransactionData.getPollName());
-
- return dataLength;
+ return getBaseLength(transactionData) + EXTRAS_LENGTH + Utf8.encodedLength(voteOnPollTransactionData.getPollName());
}
public static byte[] toBytes(TransactionData transactionData) throws TransformationException {
@@ -78,12 +78,12 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- bytes.write(Ints.toByteArray(voteOnPollTransactionData.getType().value));
- bytes.write(Longs.toByteArray(voteOnPollTransactionData.getTimestamp()));
- bytes.write(voteOnPollTransactionData.getReference());
+ transformCommonBytes(transactionData, bytes);
bytes.write(voteOnPollTransactionData.getVoterPublicKey());
+
Serialization.serializeSizedString(bytes, voteOnPollTransactionData.getPollName());
+
bytes.write(Ints.toByteArray(voteOnPollTransactionData.getOptionIndex()));
Serialization.serializeBigDecimal(bytes, voteOnPollTransactionData.getFee());
@@ -97,25 +97,4 @@ public class VoteOnPollTransactionTransformer extends TransactionTransformer {
}
}
- @SuppressWarnings("unchecked")
- public static JSONObject toJSON(TransactionData transactionData) throws TransformationException {
- JSONObject json = TransactionTransformer.getBaseJSON(transactionData);
-
- try {
- VoteOnPollTransactionData voteOnPollTransactionData = (VoteOnPollTransactionData) transactionData;
-
- byte[] voterPublicKey = voteOnPollTransactionData.getVoterPublicKey();
-
- json.put("voter", PublicKeyAccount.getAddress(voterPublicKey));
- json.put("voterPublicKey", HashCode.fromBytes(voterPublicKey).toString());
-
- json.put("name", voteOnPollTransactionData.getPollName());
- json.put("optionIndex", voteOnPollTransactionData.getOptionIndex());
- } catch (ClassCastException e) {
- throw new TransformationException(e);
- }
-
- return json;
- }
-
}
diff --git a/src/main/java/org/qora/v1feeder.java b/src/main/java/org/qora/v1feeder.java
index 8160669f..77ca458d 100644
--- a/src/main/java/org/qora/v1feeder.java
+++ b/src/main/java/org/qora/v1feeder.java
@@ -38,6 +38,7 @@ import org.qora.data.at.ATStateData;
import org.qora.data.block.BlockData;
import org.qora.data.transaction.ATTransactionData;
import org.qora.data.transaction.TransactionData;
+import org.qora.group.Group;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
import org.qora.repository.RepositoryFactory;
@@ -495,13 +496,13 @@ public class v1feeder extends Thread {
BigDecimal fee = BigDecimal.ZERO.setScale(8);
- TransactionData transactionData = new ATTransactionData(sender, recipient, amount, Asset.QORA, message, fee, timestamp, reference);
+ TransactionData transactionData = new ATTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender, recipient, amount, Asset.QORA, message, fee);
byte[] digest;
try {
digest = Crypto.digest(AtTransactionTransformer.toBytes(transactionData));
byte[] signature = Bytes.concat(digest, digest);
- transactionData = new ATTransactionData(sender, recipient, amount, Asset.QORA, message, fee, timestamp, reference, signature);
+ transactionData = new ATTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender, recipient, amount, Asset.QORA, message, fee, signature);
} catch (TransformationException e) {
throw new RuntimeException("Couldn't transform AT Transaction into bytes", e);
}
diff --git a/src/test/java/org/qora/test/ATTests.java b/src/test/java/org/qora/test/ATTests.java
index 7fa6ce63..ce9f09ac 100644
--- a/src/test/java/org/qora/test/ATTests.java
+++ b/src/test/java/org/qora/test/ATTests.java
@@ -6,6 +6,7 @@ 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.group.Group;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
import org.qora.repository.RepositoryManager;
@@ -46,8 +47,8 @@ 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,
- Asset.QORA, fee, timestamp, reference, signature);
+ DeployAtTransactionData transactionData = new DeployAtTransactionData(timestamp, Group.DEFAULT_GROUP, reference, creatorPublicKey, name, description, ATType,
+ tags, creationBytes, amount, Asset.QORA, fee, signature);
try (final Repository repository = RepositoryManager.getRepository()) {
repository.getTransactionRepository().save(transactionData);
diff --git a/src/test/java/org/qora/test/SaveTests.java b/src/test/java/org/qora/test/SaveTests.java
index 22d3eba6..b166a973 100644
--- a/src/test/java/org/qora/test/SaveTests.java
+++ b/src/test/java/org/qora/test/SaveTests.java
@@ -6,6 +6,7 @@ import java.time.Instant;
import org.junit.jupiter.api.Test;
import org.qora.account.PublicKeyAccount;
import org.qora.data.transaction.PaymentTransactionData;
+import org.qora.group.Group;
import org.qora.repository.DataException;
import org.qora.repository.Repository;
import org.qora.repository.RepositoryManager;
@@ -22,8 +23,8 @@ public class SaveTests extends Common {
byte[] signature = Base58.decode(signature58);
PublicKeyAccount sender = new PublicKeyAccount(repository, "Qsender".getBytes());
- PaymentTransactionData paymentTransactionData = new PaymentTransactionData(sender.getPublicKey(), "Qrecipient", BigDecimal.valueOf(12345L),
- BigDecimal.ONE, Instant.now().getEpochSecond(), reference, signature);
+ PaymentTransactionData paymentTransactionData = new PaymentTransactionData(Instant.now().getEpochSecond(), Group.DEFAULT_GROUP, reference,
+ sender.getPublicKey(), "Qrecipient", BigDecimal.valueOf(12345L), BigDecimal.ONE, signature);
repository.getTransactionRepository().save(paymentTransactionData);
diff --git a/src/test/java/org/qora/test/TransactionTests.java b/src/test/java/org/qora/test/TransactionTests.java
index 2b60fb01..211f8a76 100644
--- a/src/test/java/org/qora/test/TransactionTests.java
+++ b/src/test/java/org/qora/test/TransactionTests.java
@@ -32,6 +32,7 @@ import org.qora.data.transaction.VoteOnPollTransactionData;
import org.qora.data.voting.PollData;
import org.qora.data.voting.PollOptionData;
import org.qora.data.voting.VoteOnPollData;
+import org.qora.group.Group;
import org.qora.repository.AccountRepository;
import org.qora.repository.AssetRepository;
import org.qora.repository.DataException;
@@ -120,7 +121,7 @@ public class TransactionTests {
// Create test generator account
generator = new PrivateKeyAccount(repository, generatorSeed);
- accountRepository.save(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey()));
+ accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.DEFAULT_GROUP));
accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, initialGeneratorBalance));
// Create test sender account
@@ -128,7 +129,7 @@ public class TransactionTests {
// Mock account
reference = senderSeed;
- accountRepository.save(new AccountData(sender.getAddress(), reference, sender.getPublicKey()));
+ accountRepository.setLastReference(new AccountData(sender.getAddress(), reference, sender.getPublicKey(), Group.DEFAULT_GROUP));
// Mock balance
accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, initialSenderBalance));
@@ -146,7 +147,7 @@ public class TransactionTests {
BigDecimal amount = genericPaymentAmount;
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- PaymentTransactionData paymentTransactionData = new PaymentTransactionData(sender.getPublicKey(), recipient, amount, fee, timestamp, reference);
+ PaymentTransactionData paymentTransactionData = new PaymentTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), recipient, amount, fee);
Transaction paymentTransaction = new PaymentTransaction(repository, paymentTransactionData);
paymentTransaction.sign(sender);
@@ -163,8 +164,8 @@ public class TransactionTests {
BigDecimal amount = BigDecimal.valueOf(1_000L);
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- PaymentTransactionData paymentTransactionData = new PaymentTransactionData(sender.getPublicKey(), recipient.getAddress(), amount, fee, timestamp,
- reference);
+ PaymentTransactionData paymentTransactionData = new PaymentTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), recipient.getAddress(),
+ amount, fee);
Transaction paymentTransaction = new PaymentTransaction(repository, paymentTransactionData);
paymentTransaction.sign(sender);
@@ -224,8 +225,8 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- RegisterNameTransactionData registerNameTransactionData = new RegisterNameTransactionData(sender.getPublicKey(), sender.getAddress(), name, data, fee,
- timestamp, reference);
+ RegisterNameTransactionData registerNameTransactionData = new RegisterNameTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), sender.getAddress(),
+ name, data, fee);
Transaction registerNameTransaction = new RegisterNameTransaction(repository, registerNameTransactionData);
registerNameTransaction.sign(sender);
@@ -280,8 +281,8 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- UpdateNameTransactionData updateNameTransactionData = new UpdateNameTransactionData(sender.getPublicKey(), newOwner.getAddress(), name, newData,
- nameReference, fee, timestamp, reference);
+ UpdateNameTransactionData updateNameTransactionData = new UpdateNameTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(),
+ newOwner.getAddress(), name, newData, nameReference, fee);
Transaction updateNameTransaction = new UpdateNameTransaction(repository, updateNameTransactionData);
updateNameTransaction.sign(sender);
@@ -326,7 +327,7 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- SellNameTransactionData sellNameTransactionData = new SellNameTransactionData(sender.getPublicKey(), name, amount, fee, timestamp, reference);
+ SellNameTransactionData sellNameTransactionData = new SellNameTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), name, amount, fee);
Transaction sellNameTransaction = new SellNameTransaction(repository, sellNameTransactionData);
sellNameTransaction.sign(sender);
@@ -377,7 +378,7 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- CancelSellNameTransactionData cancelSellNameTransactionData = new CancelSellNameTransactionData(sender.getPublicKey(), name, fee, timestamp, reference);
+ CancelSellNameTransactionData cancelSellNameTransactionData = new CancelSellNameTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), name, fee);
Transaction cancelSellNameTransaction = new CancelSellNameTransaction(repository, cancelSellNameTransactionData);
cancelSellNameTransaction.sign(sender);
@@ -442,8 +443,8 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- BuyNameTransactionData buyNameTransactionData = new BuyNameTransactionData(buyer.getPublicKey(), name, originalNameData.getSalePrice(), seller,
- nameReference, fee, timestamp, buyersReference);
+ BuyNameTransactionData buyNameTransactionData = new BuyNameTransactionData(timestamp, Group.DEFAULT_GROUP, buyersReference, buyer.getPublicKey(),
+ name, originalNameData.getSalePrice(), seller, nameReference, fee);
Transaction buyNameTransaction = new BuyNameTransaction(repository, buyNameTransactionData);
buyNameTransaction.sign(buyer);
@@ -495,8 +496,8 @@ public class TransactionTests {
Account recipient = new PublicKeyAccount(repository, recipientSeed);
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- CreatePollTransactionData createPollTransactionData = new CreatePollTransactionData(sender.getPublicKey(), recipient.getAddress(), pollName,
- description, pollOptions, fee, timestamp, reference);
+ CreatePollTransactionData createPollTransactionData = new CreatePollTransactionData(timestamp, Group.DEFAULT_GROUP, reference,
+ sender.getPublicKey(), recipient.getAddress(), pollName, description, pollOptions, fee);
Transaction createPollTransaction = new CreatePollTransaction(repository, createPollTransactionData);
createPollTransaction.sign(sender);
@@ -549,8 +550,8 @@ public class TransactionTests {
for (int optionIndex = 0; optionIndex <= pollOptionsSize; ++optionIndex) {
// Make a vote-on-poll transaction
- VoteOnPollTransactionData voteOnPollTransactionData = new VoteOnPollTransactionData(sender.getPublicKey(), pollName, optionIndex, fee, timestamp,
- reference);
+ VoteOnPollTransactionData voteOnPollTransactionData = new VoteOnPollTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), pollName,
+ optionIndex, fee);
Transaction voteOnPollTransaction = new VoteOnPollTransaction(repository, voteOnPollTransactionData);
voteOnPollTransaction.sign(sender);
@@ -621,8 +622,8 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- IssueAssetTransactionData issueAssetTransactionData = new IssueAssetTransactionData(sender.getPublicKey(), sender.getAddress(), assetName, description,
- quantity, isDivisible, fee, timestamp, reference);
+ IssueAssetTransactionData issueAssetTransactionData = new IssueAssetTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(),
+ sender.getAddress(), assetName, description, quantity, isDivisible, fee);
Transaction issueAssetTransaction = new IssueAssetTransaction(repository, issueAssetTransactionData);
issueAssetTransaction.sign(sender);
@@ -711,8 +712,8 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- TransferAssetTransactionData transferAssetTransactionData = new TransferAssetTransactionData(sender.getPublicKey(), recipient.getAddress(), amount,
- assetId, fee, timestamp, reference);
+ TransferAssetTransactionData transferAssetTransactionData = new TransferAssetTransactionData(timestamp, Group.DEFAULT_GROUP, reference,
+ sender.getPublicKey(), recipient.getAddress(), amount, assetId, fee);
Transaction transferAssetTransaction = new TransferAssetTransaction(repository, transferAssetTransactionData);
transferAssetTransaction.sign(sender);
@@ -816,8 +817,8 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
- CreateAssetOrderTransactionData createOrderTransactionData = new CreateAssetOrderTransactionData(buyer.getPublicKey(), haveAssetId, wantAssetId, amount, price,
- fee, timestamp, buyersReference);
+ CreateAssetOrderTransactionData createOrderTransactionData = new CreateAssetOrderTransactionData(timestamp, Group.DEFAULT_GROUP, buyersReference, buyer.getPublicKey(), haveAssetId,
+ wantAssetId, amount, price, fee);
Transaction createOrderTransaction = new CreateAssetOrderTransaction(this.repository, createOrderTransactionData);
createOrderTransaction.sign(buyer);
assertTrue(createOrderTransaction.isSignatureValid());
@@ -897,7 +898,7 @@ public class TransactionTests {
BigDecimal fee = BigDecimal.ONE;
long timestamp = parentBlockData.getTimestamp() + 1_000;
byte[] buyersReference = buyer.getLastReference();
- CancelAssetOrderTransactionData cancelOrderTransactionData = new CancelAssetOrderTransactionData(buyer.getPublicKey(), orderId, fee, timestamp, buyersReference);
+ CancelAssetOrderTransactionData cancelOrderTransactionData = new CancelAssetOrderTransactionData(timestamp, Group.DEFAULT_GROUP, buyersReference, buyer.getPublicKey(), orderId, fee);
Transaction cancelOrderTransaction = new CancelAssetOrderTransaction(this.repository, cancelOrderTransactionData);
cancelOrderTransaction.sign(buyer);
@@ -972,8 +973,8 @@ public class TransactionTests {
long timestamp = parentBlockData.getTimestamp() + 1_000;
BigDecimal senderPreTradeWantBalance = sender.getConfirmedBalance(wantAssetId);
- CreateAssetOrderTransactionData createOrderTransactionData = new CreateAssetOrderTransactionData(sender.getPublicKey(), haveAssetId, wantAssetId, amount, price,
- fee, timestamp, reference);
+ CreateAssetOrderTransactionData createOrderTransactionData = new CreateAssetOrderTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), haveAssetId,
+ wantAssetId, amount, price, fee);
Transaction createOrderTransaction = new CreateAssetOrderTransaction(this.repository, createOrderTransactionData);
createOrderTransaction.sign(sender);
assertTrue(createOrderTransaction.isSignatureValid());
@@ -1081,7 +1082,7 @@ public class TransactionTests {
payments.add(paymentData);
}
- MultiPaymentTransactionData multiPaymentTransactionData = new MultiPaymentTransactionData(sender.getPublicKey(), payments, fee, timestamp, reference);
+ MultiPaymentTransactionData multiPaymentTransactionData = new MultiPaymentTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), payments, fee);
Transaction multiPaymentTransaction = new MultiPaymentTransaction(repository, multiPaymentTransactionData);
multiPaymentTransaction.sign(sender);
@@ -1150,8 +1151,8 @@ public class TransactionTests {
boolean isText = true;
boolean isEncrypted = false;
- MessageTransactionData messageTransactionData = new MessageTransactionData(version, sender.getPublicKey(), recipient.getAddress(), Asset.QORA, amount,
- data, isText, isEncrypted, fee, timestamp, reference);
+ MessageTransactionData messageTransactionData = new MessageTransactionData(timestamp, Group.DEFAULT_GROUP, reference, sender.getPublicKey(), version,
+ recipient.getAddress(), Asset.QORA, amount, data, isText, isEncrypted, fee);
Transaction messageTransaction = new MessageTransaction(repository, messageTransactionData);
messageTransaction.sign(sender);