forked from Qortal/qortal
Initial support for account flags + tx (genesis account use only atm)
This commit is contained in:
parent
85acc4d9df
commit
2dc1720af8
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
@ -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)
|
||||
|
@ -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.
|
||||
* <p>
|
||||
@ -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.
|
||||
* <p>
|
||||
* 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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
134
src/main/java/org/qora/transaction/AccountFlagsTransaction.java
Normal file
134
src/main/java/org/qora/transaction/AccountFlagsTransaction.java
Normal file
@ -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<Account> 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());
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user