From 2dc1720af886d6a7cb422a76d0cdf3eb406c952f Mon Sep 17 00:00:00 2001 From: catbref Date: Wed, 27 Feb 2019 17:00:54 +0000 Subject: [PATCH] Initial support for account flags + tx (genesis account use only atm) --- src/main/java/org/qora/account/Account.java | 12 ++ .../org/qora/data/account/AccountData.java | 14 +- .../AccountFlagsTransactionData.java | 104 ++++++++++++++ .../data/transaction/TransactionData.java | 3 +- .../qora/repository/AccountRepository.java | 10 ++ .../hsqldb/HSQLDBAccountRepository.java | 35 ++++- .../hsqldb/HSQLDBDatabaseUpdates.java | 8 ++ ...QLDBAccountFlagsTransactionRepository.java | 59 ++++++++ .../transaction/AccountFlagsTransaction.java | 134 ++++++++++++++++++ .../org/qora/transaction/Transaction.java | 4 +- .../AccountFlagsTransactionTransformer.java | 99 +++++++++++++ .../java/org/qora/test/TransactionTests.java | 4 +- 12 files changed, 478 insertions(+), 8 deletions(-) create mode 100644 src/main/java/org/qora/data/transaction/AccountFlagsTransactionData.java create mode 100644 src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAccountFlagsTransactionRepository.java create mode 100644 src/main/java/org/qora/transaction/AccountFlagsTransaction.java create mode 100644 src/main/java/org/qora/transform/transaction/AccountFlagsTransactionTransformer.java diff --git a/src/main/java/org/qora/account/Account.java b/src/main/java/org/qora/account/Account.java index d907629e..1f760fb9 100644 --- a/src/main/java/org/qora/account/Account.java +++ b/src/main/java/org/qora/account/Account.java @@ -226,4 +226,16 @@ public class Account { LOGGER.trace(String.format("Account %s defaultGroupId now %d", accountData.getAddress(), defaultGroupId)); } + // Account flags + + public Integer getFlags() throws DataException { + return this.repository.getAccountRepository().getFlags(this.address); + } + + public void setFlags(int flags) throws DataException { + AccountData accountData = this.buildAccountData(); + accountData.setFlags(flags); + this.repository.getAccountRepository().setFlags(accountData); + } + } diff --git a/src/main/java/org/qora/data/account/AccountData.java b/src/main/java/org/qora/data/account/AccountData.java index 0ea79259..71de7c3b 100644 --- a/src/main/java/org/qora/data/account/AccountData.java +++ b/src/main/java/org/qora/data/account/AccountData.java @@ -14,6 +14,7 @@ public class AccountData { protected byte[] reference; protected byte[] publicKey; protected int defaultGroupId; + protected int flags; // Constructors @@ -21,15 +22,16 @@ public class AccountData { protected AccountData() { } - public AccountData(String address, byte[] reference, byte[] publicKey, int defaultGroupId) { + public AccountData(String address, byte[] reference, byte[] publicKey, int defaultGroupId, int flags) { this.address = address; this.reference = reference; this.publicKey = publicKey; this.defaultGroupId = defaultGroupId; + this.flags = flags; } public AccountData(String address) { - this(address, null, null, Group.NO_GROUP); + this(address, null, null, Group.NO_GROUP, 0); } // Getters/Setters @@ -62,6 +64,14 @@ public class AccountData { this.defaultGroupId = defaultGroupId; } + public int getFlags() { + return this.flags; + } + + public void setFlags(int flags) { + this.flags = flags; + } + // Comparison @Override diff --git a/src/main/java/org/qora/data/transaction/AccountFlagsTransactionData.java b/src/main/java/org/qora/data/transaction/AccountFlagsTransactionData.java new file mode 100644 index 00000000..e346d5f0 --- /dev/null +++ b/src/main/java/org/qora/data/transaction/AccountFlagsTransactionData.java @@ -0,0 +1,104 @@ +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.XmlElement; + +import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue; +import org.qora.account.GenesisAccount; +import org.qora.block.GenesisBlock; +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}) +//JAXB: use this subclass if XmlDiscriminatorNode matches XmlDiscriminatorValue below: +@XmlDiscriminatorValue("ACCOUNT_FLAGS") +public class AccountFlagsTransactionData extends TransactionData { + + private String target; + private int andMask; + private int orMask; + private int xorMask; + private Integer previousFlags; + + // Constructors + + // For JAXB + protected AccountFlagsTransactionData() { + super(TransactionType.ACCOUNT_FLAGS); + } + + public void afterUnmarshal(Unmarshaller u, Object parent) { + /* + * If we're being constructed as part of the genesis block info inside blockchain config + * and no specific creator's public key is supplied + * then use genesis account's public key. + */ + if (parent instanceof GenesisBlock.GenesisInfo && this.creatorPublicKey == null) + this.creatorPublicKey = GenesisAccount.PUBLIC_KEY; + } + + public AccountFlagsTransactionData(long timestamp, int groupId, byte[] reference, byte[] creatorPublicKey, String target, int andMask, int orMask, + int xorMask, Integer previousFlags, BigDecimal fee, byte[] signature) { + super(TransactionType.ACCOUNT_FLAGS, timestamp, groupId, reference, creatorPublicKey, fee, signature); + + this.target = target; + this.andMask = andMask; + this.orMask = orMask; + this.xorMask = xorMask; + this.previousFlags = previousFlags; + } + + // Typically used in deserialization context + public AccountFlagsTransactionData(long timestamp, int groupId, byte[] reference, byte[] creatorPublicKey, String target, int andMask, int orMask, + int xorMask, BigDecimal fee, byte[] signature) { + this(timestamp, groupId, reference, creatorPublicKey, target, andMask, orMask, xorMask, null, fee, signature); + } + + // Getters / setters + + public String getTarget() { + return this.target; + } + + public int getAndMask() { + return this.andMask; + } + + public int getOrMask() { + return this.orMask; + } + + public int getXorMask() { + return this.xorMask; + } + + public Integer getPreviousFlags() { + return this.previousFlags; + } + + public void setPreviousFlags(Integer previousFlags) { + this.previousFlags = previousFlags; + } + + // 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 2c102440..aaa20e6e 100644 --- a/src/main/java/org/qora/data/transaction/TransactionData.java +++ b/src/main/java/org/qora/data/transaction/TransactionData.java @@ -37,7 +37,8 @@ import io.swagger.v3.oas.annotations.media.Schema.AccessMode; GroupKickTransactionData.class, GroupInviteTransactionData.class, JoinGroupTransactionData.class, LeaveGroupTransactionData.class, GroupApprovalTransactionData.class, SetGroupTransactionData.class, - UpdateAssetTransactionData.class + UpdateAssetTransactionData.class, + AccountFlagsTransactionData.class }) //All properties to be converted to JSON via JAXB @XmlAccessorType(XmlAccessType.FIELD) diff --git a/src/main/java/org/qora/repository/AccountRepository.java b/src/main/java/org/qora/repository/AccountRepository.java index fcbceff4..50950441 100644 --- a/src/main/java/org/qora/repository/AccountRepository.java +++ b/src/main/java/org/qora/repository/AccountRepository.java @@ -18,6 +18,9 @@ public interface AccountRepository { /** Returns account's default groupID or null if account not found. */ public Integer getDefaultGroupId(String address) throws DataException; + /** Returns account's flags or null if account not found. */ + public Integer getFlags(String address) throws DataException; + /** * Ensures at least minimal account info in repository. *

@@ -39,6 +42,13 @@ public interface AccountRepository { */ public void setDefaultGroupId(AccountData accountData) throws DataException; + /** + * Saves account's flags, and public key if present, in repository. + *

+ * Note: ignores other fields like last reference, default groupID. + */ + public void setFlags(AccountData accountData) throws DataException; + public void delete(String address) throws DataException; // Account balances diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java index 5e933fb0..d7d1bf1f 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBAccountRepository.java @@ -26,15 +26,16 @@ public class HSQLDBAccountRepository implements AccountRepository { @Override 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)) { + try (ResultSet resultSet = this.repository.checkedExecute("SELECT reference, public_key, default_group_id, flags 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); + int flags = resultSet.getInt(4); - return new AccountData(address, reference, publicKey, defaultGroupId); + return new AccountData(address, reference, publicKey, defaultGroupId, flags); } catch (SQLException e) { throw new DataException("Unable to fetch account info from repository", e); } @@ -65,6 +66,19 @@ public class HSQLDBAccountRepository implements AccountRepository { } } + @Override + public Integer getFlags(String address) throws DataException { + try (ResultSet resultSet = this.repository.checkedExecute("SELECT flags 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 flags from repository", e); + } + } + @Override public void ensureAccount(AccountData accountData) throws DataException { HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts"); @@ -116,6 +130,23 @@ public class HSQLDBAccountRepository implements AccountRepository { } } + @Override + public void setFlags(AccountData accountData) throws DataException { + HSQLDBSaver saveHelper = new HSQLDBSaver("Accounts"); + + saveHelper.bind("account", accountData.getAddress()).bind("flags", accountData.getFlags()); + + 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 flags into repository", e); + } + } + @Override public void delete(String address) throws DataException { // NOTE: Account balances are deleted automatically by the database thanks to "ON DELETE CASCADE" in AccountBalances' FOREIGN KEY diff --git a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java index 363efce6..536de9d0 100644 --- a/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java +++ b/src/main/java/org/qora/repository/hsqldb/HSQLDBDatabaseUpdates.java @@ -690,6 +690,14 @@ public class HSQLDBDatabaseUpdates { stmt.execute("ALTER TABLE AssetTrades ADD initiator_saving QoraAmount NOT NULL DEFAULT 0"); break; + case 44: + // Account flags + stmt.execute("ALTER TABLE Accounts ADD COLUMN flags INT NOT NULL DEFAULT 0"); + // Corresponding transaction to set/clear flags + stmt.execute("CREATE TABLE AccountFlagsTransactions (signature Signature, creator QoraPublicKey NOT NULL, target QoraAddress NOT NULL, and_mask INT NOT NULL, or_mask INT NOT NULL, xor_mask INT NOT NULL, " + + "previous_flags INT, PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)"); + break; + default: // nothing to do return false; diff --git a/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAccountFlagsTransactionRepository.java b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAccountFlagsTransactionRepository.java new file mode 100644 index 00000000..c70fc600 --- /dev/null +++ b/src/main/java/org/qora/repository/hsqldb/transaction/HSQLDBAccountFlagsTransactionRepository.java @@ -0,0 +1,59 @@ +package org.qora.repository.hsqldb.transaction; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.qora.data.transaction.AccountFlagsTransactionData; +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 HSQLDBAccountFlagsTransactionRepository extends HSQLDBTransactionRepository { + + public HSQLDBAccountFlagsTransactionRepository(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 target, and_mask, or_mask, xor_mask, previous_flags FROM AccountFlagsTransactions WHERE signature = ?", signature)) { + if (resultSet == null) + return null; + + String target = resultSet.getString(1); + int andMask = resultSet.getInt(2); + int orMask = resultSet.getInt(3); + int xorMask = resultSet.getInt(4); + + Integer previousFlags = resultSet.getInt(5); + if (resultSet.wasNull()) + previousFlags = null; + + return new AccountFlagsTransactionData(timestamp, txGroupId, reference, creatorPublicKey, target, andMask, orMask, xorMask, previousFlags, fee, + signature); + } catch (SQLException e) { + throw new DataException("Unable to fetch account flags transaction from repository", e); + } + } + + @Override + public void save(TransactionData transactionData) throws DataException { + AccountFlagsTransactionData accountFlagsTransactionData = (AccountFlagsTransactionData) transactionData; + + HSQLDBSaver saveHelper = new HSQLDBSaver("AccountFlagsTransactions"); + + saveHelper.bind("signature", accountFlagsTransactionData.getSignature()).bind("creator", accountFlagsTransactionData.getCreatorPublicKey()) + .bind("target", accountFlagsTransactionData.getTarget()).bind("and_mask", accountFlagsTransactionData.getAndMask()) + .bind("or_mask", accountFlagsTransactionData.getOrMask()).bind("xor_mask", accountFlagsTransactionData.getXorMask()) + .bind("previous_flags", accountFlagsTransactionData.getPreviousFlags()); + + try { + saveHelper.execute(this.repository); + } catch (SQLException e) { + throw new DataException("Unable to save account flags transaction into repository", e); + } + } + +} diff --git a/src/main/java/org/qora/transaction/AccountFlagsTransaction.java b/src/main/java/org/qora/transaction/AccountFlagsTransaction.java new file mode 100644 index 00000000..3ba20986 --- /dev/null +++ b/src/main/java/org/qora/transaction/AccountFlagsTransaction.java @@ -0,0 +1,134 @@ +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.GenesisAccount; +import org.qora.asset.Asset; +import org.qora.data.transaction.AccountFlagsTransactionData; +import org.qora.data.transaction.TransactionData; +import org.qora.repository.DataException; +import org.qora.repository.Repository; + +public class AccountFlagsTransaction extends Transaction { + + // Properties + private AccountFlagsTransactionData accountFlagsTransactionData; + + // Constructors + + public AccountFlagsTransaction(Repository repository, TransactionData transactionData) { + super(repository, transactionData); + + this.accountFlagsTransactionData = (AccountFlagsTransactionData) 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; + + if (address.equals(this.getTarget().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 + + public Account getTarget() { + return new Account(this.repository, this.accountFlagsTransactionData.getTarget()); + } + + // Processing + + @Override + public ValidationResult isValid() throws DataException { + Account creator = getCreator(); + + // Only genesis account can modify flags + if (!creator.getAddress().equals(new GenesisAccount(repository).getAddress())) + return ValidationResult.NO_FLAG_PERMISSION; + + // Check fee is zero or positive + if (accountFlagsTransactionData.getFee().compareTo(BigDecimal.ZERO) < 0) + return ValidationResult.NEGATIVE_FEE; + + // Check reference + if (!Arrays.equals(creator.getLastReference(), accountFlagsTransactionData.getReference())) + return ValidationResult.INVALID_REFERENCE; + + // Check creator has enough funds + if (creator.getConfirmedBalance(Asset.QORA).compareTo(accountFlagsTransactionData.getFee()) < 0) + return ValidationResult.NO_BALANCE; + + return ValidationResult.OK; + } + + @Override + public void process() throws DataException { + Account target = getTarget(); + int previousFlags = target.getFlags(); + + accountFlagsTransactionData.setPreviousFlags(previousFlags); + + // Save this transaction with target account's previous flags value + this.repository.getTransactionRepository().save(accountFlagsTransactionData); + + // Set account's new flags + int newFlags = previousFlags & accountFlagsTransactionData.getAndMask() + | accountFlagsTransactionData.getOrMask() ^ accountFlagsTransactionData.getXorMask(); + + target.setFlags(newFlags); + + // Update creator's balance + Account creator = getCreator(); + creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).subtract(accountFlagsTransactionData.getFee())); + + // Update creator's reference + creator.setLastReference(accountFlagsTransactionData.getSignature()); + } + + @Override + public void orphan() throws DataException { + // Revert + Account target = getTarget(); + + target.setFlags(accountFlagsTransactionData.getPreviousFlags()); + + // Delete this transaction itself + this.repository.getTransactionRepository().delete(accountFlagsTransactionData); + + Account creator = getCreator(); + + // Update creator's balance + creator.setConfirmedBalance(Asset.QORA, creator.getConfirmedBalance(Asset.QORA).add(accountFlagsTransactionData.getFee())); + + // Update creator's reference + creator.setLastReference(accountFlagsTransactionData.getReference()); + } + +} diff --git a/src/main/java/org/qora/transaction/Transaction.java b/src/main/java/org/qora/transaction/Transaction.java index 43d52159..9f078f21 100644 --- a/src/main/java/org/qora/transaction/Transaction.java +++ b/src/main/java/org/qora/transaction/Transaction.java @@ -72,7 +72,8 @@ public abstract class Transaction { LEAVE_GROUP(32, false), GROUP_APPROVAL(33, false), SET_GROUP(34, false), - UPDATE_ASSET(35, true); + UPDATE_ASSET(35, true), + ACCOUNT_FLAGS(36, false); public final int value; public final boolean needsApproval; @@ -190,6 +191,7 @@ public abstract class Transaction { MULTIPLE_NAMES_FORBIDDEN(69), INVALID_ASSET_OWNER(70), AT_IS_FINISHED(71), + NO_FLAG_PERMISSION(72), NOT_YET_RELEASED(1000); public final int value; diff --git a/src/main/java/org/qora/transform/transaction/AccountFlagsTransactionTransformer.java b/src/main/java/org/qora/transform/transaction/AccountFlagsTransactionTransformer.java new file mode 100644 index 00000000..fd892fd1 --- /dev/null +++ b/src/main/java/org/qora/transform/transaction/AccountFlagsTransactionTransformer.java @@ -0,0 +1,99 @@ +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.AccountFlagsTransactionData; +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 AccountFlagsTransactionTransformer extends TransactionTransformer { + + // Property lengths + private static final int TARGET_LENGTH = ADDRESS_LENGTH; + private static final int AND_MASK_LENGTH = INT_LENGTH; + private static final int OR_MASK_LENGTH = INT_LENGTH; + private static final int XOR_MASK_LENGTH = INT_LENGTH; + + private static final int EXTRAS_LENGTH = TARGET_LENGTH + AND_MASK_LENGTH + OR_MASK_LENGTH + XOR_MASK_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("target account's address", TransformationType.ADDRESS); + layout.add("flags AND mask", TransformationType.INT); + layout.add("flags OR mask", TransformationType.INT); + layout.add("flags XOR mask", 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); + + String target = Serialization.deserializeAddress(byteBuffer); + + int andMask = byteBuffer.getInt(); + int orMask = byteBuffer.getInt(); + int xorMask = byteBuffer.getInt(); + + BigDecimal fee = Serialization.deserializeBigDecimal(byteBuffer); + + byte[] signature = new byte[SIGNATURE_LENGTH]; + byteBuffer.get(signature); + + return new AccountFlagsTransactionData(timestamp, txGroupId, reference, creatorPublicKey, target, andMask, orMask, xorMask, fee, signature); + } + + public static int getDataLength(TransactionData transactionData) throws TransformationException { + return getBaseLength(transactionData) + EXTRAS_LENGTH; + } + + public static byte[] toBytes(TransactionData transactionData) throws TransformationException { + try { + AccountFlagsTransactionData accountFlagsTransactionData = (AccountFlagsTransactionData) transactionData; + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + + transformCommonBytes(transactionData, bytes); + + Serialization.serializeAddress(bytes, accountFlagsTransactionData.getTarget()); + + bytes.write(Ints.toByteArray(accountFlagsTransactionData.getAndMask())); + bytes.write(Ints.toByteArray(accountFlagsTransactionData.getOrMask())); + bytes.write(Ints.toByteArray(accountFlagsTransactionData.getXorMask())); + + Serialization.serializeBigDecimal(bytes, accountFlagsTransactionData.getFee()); + + if (accountFlagsTransactionData.getSignature() != null) + bytes.write(accountFlagsTransactionData.getSignature()); + + return bytes.toByteArray(); + } catch (IOException | ClassCastException e) { + throw new TransformationException(e); + } + } + +} diff --git a/src/test/java/org/qora/test/TransactionTests.java b/src/test/java/org/qora/test/TransactionTests.java index e738cdce..3844ed95 100644 --- a/src/test/java/org/qora/test/TransactionTests.java +++ b/src/test/java/org/qora/test/TransactionTests.java @@ -103,7 +103,7 @@ public class TransactionTests extends Common { // Create test generator account generator = new PrivateKeyAccount(repository, generatorSeed); - accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.NO_GROUP)); + accountRepository.setLastReference(new AccountData(generator.getAddress(), generatorSeed, generator.getPublicKey(), Group.NO_GROUP, 0)); accountRepository.save(new AccountBalanceData(generator.getAddress(), Asset.QORA, initialGeneratorBalance)); // Create test sender account @@ -111,7 +111,7 @@ public class TransactionTests extends Common { // Mock account reference = senderSeed; - accountRepository.setLastReference(new AccountData(sender.getAddress(), reference, sender.getPublicKey(), Group.NO_GROUP)); + accountRepository.setLastReference(new AccountData(sender.getAddress(), reference, sender.getPublicKey(), Group.NO_GROUP, 0)); // Mock balance accountRepository.save(new AccountBalanceData(sender.getAddress(), Asset.QORA, initialSenderBalance));