diff --git a/lib/org/ciyam/at/1.0/at-1.0.jar b/lib/org/ciyam/at/1.0/at-1.0.jar
index 1b554f34..669e9887 100644
Binary files a/lib/org/ciyam/at/1.0/at-1.0.jar and b/lib/org/ciyam/at/1.0/at-1.0.jar differ
diff --git a/lib/org/ciyam/at/1.0/at-1.0.jar.md5 b/lib/org/ciyam/at/1.0/at-1.0.jar.md5
index c06cf86a..be960be8 100644
--- a/lib/org/ciyam/at/1.0/at-1.0.jar.md5
+++ b/lib/org/ciyam/at/1.0/at-1.0.jar.md5
@@ -1 +1 @@
-1d6f5d634a2c4e570a5a8af260a51653
\ No newline at end of file
+ab1560171ae5c6c15b0dfa8e6cccc7f8
\ No newline at end of file
diff --git a/lib/org/ciyam/at/1.0/at-1.0.jar.sha1 b/lib/org/ciyam/at/1.0/at-1.0.jar.sha1
index 2f748fd6..29767395 100644
--- a/lib/org/ciyam/at/1.0/at-1.0.jar.sha1
+++ b/lib/org/ciyam/at/1.0/at-1.0.jar.sha1
@@ -1 +1 @@
-c6387380bc5db1f0a98ecbb480b17bd89b564401
\ No newline at end of file
+c293c9656f43b432a08053f19ec5aa0de1cd10ea
\ No newline at end of file
diff --git a/lib/org/ciyam/at/maven-metadata-local.xml b/lib/org/ciyam/at/maven-metadata-local.xml
new file mode 100644
index 00000000..513f5312
--- /dev/null
+++ b/lib/org/ciyam/at/maven-metadata-local.xml
@@ -0,0 +1,12 @@
+
+
+ org.ciyam
+ at
+
+ 1.0
+
+ 1.0
+
+ 20181015085522
+
+
diff --git a/lib/org/ciyam/at/maven-metadata.xml b/lib/org/ciyam/at/maven-metadata.xml
index 9b556545..dd714561 100644
--- a/lib/org/ciyam/at/maven-metadata.xml
+++ b/lib/org/ciyam/at/maven-metadata.xml
@@ -7,6 +7,6 @@
1.0
- 20181003154752
+ 20181015081124
diff --git a/lib/org/ciyam/at/maven-metadata.xml.md5 b/lib/org/ciyam/at/maven-metadata.xml.md5
index de530860..e8f9b7d2 100644
--- a/lib/org/ciyam/at/maven-metadata.xml.md5
+++ b/lib/org/ciyam/at/maven-metadata.xml.md5
@@ -1 +1 @@
-bc81bc1f9b74a4eececd5dd8b29e47d8
\ No newline at end of file
+2369bf36c52580a89d5ea71a0f037a82
\ No newline at end of file
diff --git a/lib/org/ciyam/at/maven-metadata.xml.sha1 b/lib/org/ciyam/at/maven-metadata.xml.sha1
index 1746aa6b..88816e70 100644
--- a/lib/org/ciyam/at/maven-metadata.xml.sha1
+++ b/lib/org/ciyam/at/maven-metadata.xml.sha1
@@ -1 +1 @@
-feefde4343bda4d6e13159e5c01f8b4f8963a1bc
\ No newline at end of file
+6bc38899b93ffce2286ae26f7af0b2d8b69db3cf
\ No newline at end of file
diff --git a/src/data/transaction/ATTransactionData.java b/src/data/transaction/ATTransactionData.java
index 43053561..8d9f99de 100644
--- a/src/data/transaction/ATTransactionData.java
+++ b/src/data/transaction/ATTransactionData.java
@@ -10,22 +10,25 @@ public class ATTransactionData extends TransactionData {
private byte[] senderPublicKey;
private String recipient;
private BigDecimal amount;
+ private Long assetId;
private byte[] message;
// Constructors
- public ATTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, byte[] message, BigDecimal fee, long timestamp, byte[] reference,
- byte[] signature) {
+ public ATTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, Long assetId, byte[] message, BigDecimal fee, long timestamp,
+ byte[] reference, byte[] signature) {
super(TransactionType.AT, fee, senderPublicKey, timestamp, reference, signature);
this.senderPublicKey = senderPublicKey;
this.recipient = recipient;
this.amount = amount;
+ this.assetId = assetId;
this.message = message;
}
- public ATTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, byte[] message, BigDecimal fee, long timestamp, byte[] reference) {
- this(senderPublicKey, recipient, amount, message, fee, timestamp, reference, null);
+ public ATTransactionData(byte[] senderPublicKey, String recipient, BigDecimal amount, Long assetId, byte[] message, BigDecimal fee, long timestamp,
+ byte[] reference) {
+ this(senderPublicKey, recipient, amount, assetId, message, fee, timestamp, reference, null);
}
// Getters/Setters
@@ -42,6 +45,10 @@ public class ATTransactionData extends TransactionData {
return this.amount;
}
+ public Long getAssetId() {
+ return this.assetId;
+ }
+
public byte[] getMessage() {
return this.message;
}
diff --git a/src/qora/at/AT.java b/src/qora/at/AT.java
index 8c1a9b99..292ff62b 100644
--- a/src/qora/at/AT.java
+++ b/src/qora/at/AT.java
@@ -1,5 +1,7 @@
package qora.at;
+import java.nio.ByteBuffer;
+
import org.ciyam.at.MachineState;
import data.at.ATData;
@@ -26,20 +28,51 @@ public class AT {
public AT(Repository repository, DeployATTransactionData deployATTransactionData) throws DataException {
this.repository = repository;
- MachineState machineState = new MachineState(deployATTransactionData.getCreationBytes());
-
- this.atData = new ATData(deployATTransactionData.getATAddress(), machineState.version, machineState.codeByteBuffer.array(), machineState.isSleeping,
- machineState.sleepUntilHeight, machineState.isFinished, machineState.hadFatalError, machineState.isFrozen, machineState.frozenBalance,
- deployATTransactionData.getSignature());
-
- String atAddress = this.atData.getATAddress();
-
+ String atAddress = deployATTransactionData.getATAddress();
int height = this.repository.getBlockRepository().getBlockchainHeight();
- byte[] stateData = machineState.toBytes();
- this.atStateData = new ATStateData(atAddress, height, stateData);
+ byte[] creationBytes = deployATTransactionData.getCreationBytes();
+ short version = (short) (creationBytes[0] | (creationBytes[1] << 8)); // Little-endian
+
+ if (version >= 2) {
+ MachineState machineState = new MachineState(deployATTransactionData.getCreationBytes());
+
+ this.atData = new ATData(atAddress, machineState.version, machineState.getCodeBytes(), machineState.getIsSleeping(),
+ machineState.getSleepUntilHeight(), machineState.getIsFinished(), machineState.getHadFatalError(), machineState.getIsFrozen(),
+ machineState.getFrozenBalance(), deployATTransactionData.getSignature());
+
+ this.atStateData = new ATStateData(atAddress, height, machineState.toBytes());
+ } else {
+ // Legacy v1 AT in 'dead' state
+ // Extract code bytes length
+ ByteBuffer byteBuffer = ByteBuffer.wrap(deployATTransactionData.getCreationBytes());
+
+ short numCodePages = byteBuffer.get(2 + 2);
+
+ byteBuffer.position(6 * 2 + 8);
+ int codeLen = 0;
+
+ if (numCodePages * 256 < 257) {
+ codeLen = (int) (byteBuffer.get() & 0xff);
+ } else if (numCodePages * 256 < Short.MAX_VALUE + 1) {
+ codeLen = byteBuffer.getShort() & 0xffff;
+ } else if (numCodePages * 256 <= Integer.MAX_VALUE) {
+ codeLen = byteBuffer.getInt();
+ }
+
+ // Extract code bytes
+ byte[] codeBytes = new byte[codeLen];
+ byteBuffer.get(codeBytes);
+
+ this.atData = new ATData(deployATTransactionData.getATAddress(), 1, codeBytes, false, null, true, false, false, (Long) null,
+ deployATTransactionData.getSignature());
+
+ this.atStateData = new ATStateData(deployATTransactionData.getATAddress(), height, null);
+ }
}
+ // Processing
+
public void deploy() throws DataException {
this.repository.getATRepository().save(this.atData);
this.repository.getATRepository().save(this.atStateData);
diff --git a/src/qora/block/Block.java b/src/qora/block/Block.java
index 5dc2340f..44fdea7d 100644
--- a/src/qora/block/Block.java
+++ b/src/qora/block/Block.java
@@ -612,7 +612,7 @@ public class Block {
Transaction.ValidationResult validationResult = transaction.isValid();
if (validationResult != Transaction.ValidationResult.OK) {
LOGGER.error("Error during transaction validation, tx " + Base58.encode(transaction.getTransactionData().getSignature()) + ": "
- + validationResult.value);
+ + validationResult.name());
return ValidationResult.TRANSACTION_INVALID;
}
diff --git a/src/qora/transaction/ATTransaction.java b/src/qora/transaction/ATTransaction.java
new file mode 100644
index 00000000..e3be08e9
--- /dev/null
+++ b/src/qora/transaction/ATTransaction.java
@@ -0,0 +1,128 @@
+package qora.transaction;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import data.PaymentData;
+import data.transaction.ATTransactionData;
+import data.transaction.TransactionData;
+import qora.account.Account;
+import qora.account.PublicKeyAccount;
+import qora.assets.Asset;
+import qora.payment.Payment;
+import repository.DataException;
+import repository.Repository;
+
+public class ATTransaction extends Transaction {
+
+ // Properties
+ private ATTransactionData atTransactionData;
+
+ // Other useful constants
+ public static final int MAX_DATA_SIZE = 256;
+
+ // Constructors
+
+ public ATTransaction(Repository repository, TransactionData transactionData) {
+ super(repository, transactionData);
+
+ this.atTransactionData = (ATTransactionData) this.transactionData;
+ }
+
+ // More information
+
+ @Override
+ public List getRecipientAccounts() throws DataException {
+ return Collections.singletonList(new Account(this.repository, atTransactionData.getRecipient()));
+ }
+
+ @Override
+ public boolean isInvolved(Account account) throws DataException {
+ String address = account.getAddress();
+
+ if (address.equals(this.getSender().getAddress()))
+ return true;
+
+ if (address.equals(atTransactionData.getRecipient()))
+ return true;
+
+ return false;
+ }
+
+ @Override
+ public BigDecimal getAmount(Account account) throws DataException {
+ String address = account.getAddress();
+ BigDecimal amount = BigDecimal.ZERO.setScale(8);
+ String senderAddress = this.getSender().getAddress();
+
+ if (address.equals(senderAddress)) {
+ amount = amount.subtract(this.atTransactionData.getFee());
+
+ if (atTransactionData.getAmount() != null && atTransactionData.getAssetId() == Asset.QORA)
+ amount = amount.subtract(atTransactionData.getAmount());
+ }
+
+ if (address.equals(atTransactionData.getRecipient()) && atTransactionData.getAmount() != null)
+ amount = amount.add(atTransactionData.getAmount());
+
+ return amount;
+ }
+
+ // Navigation
+
+ public Account getSender() throws DataException {
+ return new PublicKeyAccount(this.repository, this.atTransactionData.getSenderPublicKey());
+ }
+
+ // Processing
+
+ private PaymentData getPaymentData() {
+ if (atTransactionData.getAmount() == null)
+ return null;
+
+ return new PaymentData(atTransactionData.getRecipient(), atTransactionData.getAssetId(), atTransactionData.getAmount());
+ }
+
+ @Override
+ public ValidationResult isValid() throws DataException {
+ // Check reference is correct
+ Account sender = getSender();
+ if (!Arrays.equals(sender.getLastReference(), atTransactionData.getReference()))
+ return ValidationResult.INVALID_REFERENCE;
+
+ if (this.atTransactionData.getMessage().length > MAX_DATA_SIZE)
+ return ValidationResult.INVALID_DATA_LENGTH;
+
+ // If we have no payment then we're done
+ if (this.atTransactionData.getAmount() == null)
+ return ValidationResult.OK;
+
+ // Wrap and delegate final payment checks to Payment class
+ return new Payment(this.repository).isValid(atTransactionData.getSenderPublicKey(), getPaymentData(), atTransactionData.getFee());
+ }
+
+ @Override
+ public void process() throws DataException {
+ // Save this transaction itself
+ this.repository.getTransactionRepository().save(this.transactionData);
+
+ if (this.atTransactionData.getAmount() != null)
+ // Wrap and delegate payment processing to Payment class. Only update recipient's last reference if transferring QORA.
+ new Payment(this.repository).process(atTransactionData.getSenderPublicKey(), getPaymentData(), atTransactionData.getFee(),
+ atTransactionData.getSignature(), false);
+ }
+
+ @Override
+ public void orphan() throws DataException {
+ // Delete this transaction
+ this.repository.getTransactionRepository().delete(this.transactionData);
+
+ if (this.atTransactionData.getAmount() != null)
+ // Wrap and delegate payment processing to Payment class. Only revert recipient's last reference if transferring QORA.
+ new Payment(this.repository).orphan(atTransactionData.getSenderPublicKey(), getPaymentData(), atTransactionData.getFee(),
+ atTransactionData.getSignature(), atTransactionData.getReference(), false);
+ }
+
+}
diff --git a/src/qora/transaction/DeployATTransaction.java b/src/qora/transaction/DeployATTransaction.java
index 45d77600..699b0654 100644
--- a/src/qora/transaction/DeployATTransaction.java
+++ b/src/qora/transaction/DeployATTransaction.java
@@ -75,6 +75,13 @@ public class DeployATTransaction extends Transaction {
return amount;
}
+ /** Returns AT version from the header bytes */
+ private short getVersion() {
+ byte[] creationBytes = deployATTransactionData.getCreationBytes();
+ short version = (short) (creationBytes[0] | (creationBytes[1] << 8)); // Little-endian
+ return version;
+ }
+
/** Make sure deployATTransactionData has an ATAddress */
private void ensureATAddress() throws DataException {
if (this.deployATTransactionData.getATAddress() != null)
@@ -82,7 +89,7 @@ public class DeployATTransaction extends Transaction {
int blockHeight = this.getHeight();
if (blockHeight == 0)
- blockHeight = this.repository.getBlockRepository().getBlockchainHeight();
+ blockHeight = this.repository.getBlockRepository().getBlockchainHeight() + 1;
try {
byte[] name = this.deployATTransactionData.getName().getBytes("UTF-8");
@@ -163,11 +170,8 @@ public class DeployATTransaction extends Transaction {
if (creator.getConfirmedBalance(Asset.QORA).compareTo(minimumBalance) < 0)
return ValidationResult.NO_BALANCE;
- // Check creation bytes are valid (for v3+)
- byte[] creationBytes = deployATTransactionData.getCreationBytes();
- short version = (short) (creationBytes[0] | (creationBytes[1] << 8)); // Little-endian
-
- if (version >= 3) {
+ // Check creation bytes are valid (for v2+)
+ if (this.getVersion() >= 2) {
// Do actual validation
} else {
// Skip validation for old, dead ATs
@@ -194,6 +198,14 @@ public class DeployATTransaction extends Transaction {
// Update creator's reference
creator.setLastReference(deployATTransactionData.getSignature());
+
+ // Update AT's reference, which also creates AT account
+ Account atAccount = this.getATAccount();
+ atAccount.setLastReference(deployATTransactionData.getSignature());
+
+ // Update AT's balance
+ atAccount.setConfirmedBalance(Asset.QORA, deployATTransactionData.getAmount());
+
}
@Override
@@ -212,6 +224,9 @@ public class DeployATTransaction extends Transaction {
// Update creator's reference
creator.setLastReference(deployATTransactionData.getReference());
+
+ // Delete AT's account
+ this.repository.getAccountRepository().delete(this.deployATTransactionData.getATAddress());
}
}
diff --git a/src/qora/transaction/Transaction.java b/src/qora/transaction/Transaction.java
index aaba8836..f532e3bf 100644
--- a/src/qora/transaction/Transaction.java
+++ b/src/qora/transaction/Transaction.java
@@ -193,11 +193,14 @@ public abstract class Transaction {
case MULTIPAYMENT:
return new MultiPaymentTransaction(repository, transactionData);
+ case DEPLOY_AT:
+ return new DeployATTransaction(repository, transactionData);
+
case MESSAGE:
return new MessageTransaction(repository, transactionData);
- case DEPLOY_AT:
- return new DeployATTransaction(repository, transactionData);
+ case AT:
+ return new ATTransaction(repository, transactionData);
default:
throw new IllegalStateException("Unsupported transaction type [" + transactionData.getType().value + "] during fetch from repository");
diff --git a/src/repository/AccountRepository.java b/src/repository/AccountRepository.java
index d740fe80..5983ebfb 100644
--- a/src/repository/AccountRepository.java
+++ b/src/repository/AccountRepository.java
@@ -11,6 +11,8 @@ public interface AccountRepository {
public void save(AccountData accountData) throws DataException;
+ public void delete(String address) throws DataException;
+
// Account balances
public AccountBalanceData getBalance(String address, long assetId) throws DataException;
diff --git a/src/repository/hsqldb/HSQLDBATRepository.java b/src/repository/hsqldb/HSQLDBATRepository.java
index 5c2cc88d..4cb0cd23 100644
--- a/src/repository/hsqldb/HSQLDBATRepository.java
+++ b/src/repository/hsqldb/HSQLDBATRepository.java
@@ -69,7 +69,7 @@ public class HSQLDBATRepository implements ATRepository {
@Override
public void delete(String atAddress) throws DataException {
try {
- this.repository.delete("ATs", "atAddress = ?", atAddress);
+ this.repository.delete("ATs", "AT_address = ?", atAddress);
// AT States also deleted via ON DELETE CASCADE
} catch (SQLException e) {
throw new DataException("Unable to delete AT from repository", e);
diff --git a/src/repository/hsqldb/HSQLDBAccountRepository.java b/src/repository/hsqldb/HSQLDBAccountRepository.java
index 1e2c669e..d56604b3 100644
--- a/src/repository/hsqldb/HSQLDBAccountRepository.java
+++ b/src/repository/hsqldb/HSQLDBAccountRepository.java
@@ -17,6 +17,8 @@ public class HSQLDBAccountRepository implements AccountRepository {
this.repository = repository;
}
+ // General account
+
@Override
public AccountData getAccount(String address) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT reference FROM Accounts WHERE account = ?", address)) {
@@ -41,6 +43,19 @@ public class HSQLDBAccountRepository implements AccountRepository {
}
}
+ @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
+ // definition.
+ try {
+ this.repository.delete("Accounts", "account = ?", address);
+ } catch (SQLException e) {
+ throw new DataException("Unable to delete account from repository", e);
+ }
+ }
+
+ // Account balances
+
@Override
public AccountBalanceData getBalance(String address, long assetId) throws DataException {
try (ResultSet resultSet = this.repository.checkedExecute("SELECT balance FROM AccountBalances WHERE account = ? and asset_id = ?", address, assetId)) {
diff --git a/src/repository/hsqldb/HSQLDBDatabaseUpdates.java b/src/repository/hsqldb/HSQLDBDatabaseUpdates.java
index f3f1dba7..e8efb45a 100644
--- a/src/repository/hsqldb/HSQLDBDatabaseUpdates.java
+++ b/src/repository/hsqldb/HSQLDBDatabaseUpdates.java
@@ -99,6 +99,7 @@ public class HSQLDBDatabaseUpdates {
stmt.execute("CREATE TYPE ATType AS VARCHAR(200) COLLATE SQL_TEXT_UCC_NO_PAD");
stmt.execute("CREATE TYPE ATCode AS BLOB(64K)"); // 16bit * 1
stmt.execute("CREATE TYPE ATState AS BLOB(1M)"); // 16bit * 8 + 16bit * 4 + 16bit * 4
+ stmt.execute("CREATE TYPE ATStateHash as VARBINARY(32)");
stmt.execute("CREATE TYPE ATMessage AS VARBINARY(256)");
break;
@@ -302,7 +303,7 @@ public class HSQLDBDatabaseUpdates {
// Accounts
stmt.execute("CREATE TABLE Accounts (account QoraAddress, reference Signature, PRIMARY KEY (account))");
stmt.execute("CREATE TABLE AccountBalances (account QoraAddress, asset_id AssetID, balance QoraAmount NOT NULL, "
- + "PRIMARY KEY (account, asset_id))");
+ + "PRIMARY KEY (account, asset_id), FOREIGN KEY (account) REFERENCES Accounts (account) ON DELETE CASCADE)");
break;
case 23:
@@ -358,11 +359,12 @@ public class HSQLDBDatabaseUpdates {
// For finding executable ATs
stmt.execute("CREATE INDEX ATIndex on ATs (is_finished, AT_address)");
// AT state on a per-block basis
- stmt.execute("CREATE TABLE ATStates (AT_address QoraAddress, height INTEGER NOT NULL, state_data ATState, "
- + "PRIMARY KEY (AT_address, height), FOREIGN KEY (AT_address) REFERENCES ATs (AT_address) ON DELETE CASCADE)");
+ stmt.execute(
+ "CREATE TABLE ATStates (AT_address QoraAddress, height INTEGER NOT NULL, state_data ATState, state_hash ATStateHash NOT NULL, fees QoraAmount NOT NULL, "
+ + "PRIMARY KEY (AT_address, height), FOREIGN KEY (AT_address) REFERENCES ATs (AT_address) ON DELETE CASCADE)");
// Generated AT Transactions
stmt.execute(
- "CREATE TABLE ATTransactions (signature Signature, sender QoraPublicKey NOT NULL, recipient QoraAddress, amount QoraAmount NOT NULL, message ATMessage, "
+ "CREATE TABLE ATTransactions (signature Signature, sender QoraPublicKey NOT NULL, recipient QoraAddress, amount QoraAmount, asset_id AssetID, message ATMessage, "
+ "PRIMARY KEY (signature), FOREIGN KEY (signature) REFERENCES Transactions (signature) ON DELETE CASCADE)");
break;
diff --git a/src/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java
new file mode 100644
index 00000000..279c540a
--- /dev/null
+++ b/src/repository/hsqldb/transaction/HSQLDBATTransactionRepository.java
@@ -0,0 +1,63 @@
+package repository.hsqldb.transaction;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import data.transaction.ATTransactionData;
+import data.transaction.TransactionData;
+import repository.DataException;
+import repository.hsqldb.HSQLDBRepository;
+import repository.hsqldb.HSQLDBSaver;
+
+public class HSQLDBATTransactionRepository extends HSQLDBTransactionRepository {
+
+ public HSQLDBATTransactionRepository(HSQLDBRepository repository) {
+ 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, asset_id, message FROM ATTransactions WHERE signature = ?",
+ signature)) {
+ if (resultSet == null)
+ return null;
+
+ byte[] senderPublicKey = resultSet.getBytes(1);
+ String recipient = resultSet.getString(2);
+
+ BigDecimal amount = resultSet.getBigDecimal(3);
+ if (resultSet.wasNull())
+ amount = null;
+
+ Long assetId = resultSet.getLong(4);
+ if (resultSet.wasNull())
+ assetId = null;
+
+ byte[] message = resultSet.getBytes(5);
+ if (resultSet.wasNull())
+ message = null;
+
+ return new ATTransactionData(senderPublicKey, recipient, amount, assetId, message, fee, timestamp, reference, signature);
+ } catch (SQLException e) {
+ throw new DataException("Unable to fetch AT transaction from repository", e);
+ }
+ }
+
+ @Override
+ public void save(TransactionData transactionData) throws DataException {
+ ATTransactionData atTransactionData = (ATTransactionData) transactionData;
+
+ HSQLDBSaver saveHelper = new HSQLDBSaver("ATTransactions");
+
+ saveHelper.bind("signature", atTransactionData.getSignature()).bind("sender", atTransactionData.getSenderPublicKey())
+ .bind("recipient", atTransactionData.getRecipient()).bind("amount", atTransactionData.getAmount())
+ .bind("asset_id", atTransactionData.getAssetId()).bind("message", atTransactionData.getMessage());
+
+ try {
+ saveHelper.execute(this.repository);
+ } catch (SQLException e) {
+ throw new DataException("Unable to save AT transaction into repository", e);
+ }
+ }
+
+}
diff --git a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
index 316ee6a7..9a2ade4d 100644
--- a/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
+++ b/src/repository/hsqldb/transaction/HSQLDBTransactionRepository.java
@@ -37,6 +37,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
private HSQLDBMultiPaymentTransactionRepository multiPaymentTransactionRepository;
private HSQLDBDeployATTransactionRepository deployATTransactionRepository;
private HSQLDBMessageTransactionRepository messageTransactionRepository;
+ private HSQLDBATTransactionRepository atTransactionRepository;
public HSQLDBTransactionRepository(HSQLDBRepository repository) {
this.repository = repository;
@@ -57,6 +58,7 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
this.multiPaymentTransactionRepository = new HSQLDBMultiPaymentTransactionRepository(repository);
this.deployATTransactionRepository = new HSQLDBDeployATTransactionRepository(repository);
this.messageTransactionRepository = new HSQLDBMessageTransactionRepository(repository);
+ this.atTransactionRepository = new HSQLDBATTransactionRepository(repository);
}
protected HSQLDBTransactionRepository() {
@@ -154,8 +156,11 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
case MESSAGE:
return this.messageTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
+ case AT:
+ return this.atTransactionRepository.fromBase(signature, reference, creatorPublicKey, timestamp, fee);
+
default:
- throw new DataException("Unsupported transaction type [" + type.value + "] during fetch from HSQLDB repository");
+ throw new DataException("Unsupported transaction type [" + type.name() + "] during fetch from HSQLDB repository");
}
}
@@ -317,8 +322,12 @@ public class HSQLDBTransactionRepository implements TransactionRepository {
this.messageTransactionRepository.save(transactionData);
break;
+ case AT:
+ this.atTransactionRepository.save(transactionData);
+ break;
+
default:
- throw new DataException("Unsupported transaction type [" + transactionData.getType().value + "] during save into HSQLDB repository");
+ throw new DataException("Unsupported transaction type [" + transactionData.getType().name() + "] during save into HSQLDB repository");
}
}
diff --git a/src/transform/transaction/DeployATTransactionTransformer.java b/src/transform/transaction/DeployATTransactionTransformer.java
index 0699084f..12d78906 100644
--- a/src/transform/transaction/DeployATTransactionTransformer.java
+++ b/src/transform/transaction/DeployATTransactionTransformer.java
@@ -97,7 +97,9 @@ public class DeployATTransactionTransformer extends TransactionTransformer {
Serialization.serializeSizedString(bytes, deployATTransactionData.getTags());
- bytes.write(deployATTransactionData.getCreationBytes());
+ byte[] creationBytes = deployATTransactionData.getCreationBytes();
+ bytes.write(Ints.toByteArray(creationBytes.length));
+ bytes.write(creationBytes);
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getAmount());
@@ -146,15 +148,14 @@ public class DeployATTransactionTransformer extends TransactionTransformer {
// Omitted: Serialization.serializeSizedString(bytes, deployATTransactionData.getTags());
- bytes.write(deployATTransactionData.getCreationBytes());
+ byte[] creationBytes = deployATTransactionData.getCreationBytes();
+ bytes.write(Ints.toByteArray(creationBytes.length));
+ bytes.write(creationBytes);
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getAmount());
Serialization.serializeBigDecimal(bytes, deployATTransactionData.getFee());
- if (deployATTransactionData.getSignature() != null)
- bytes.write(deployATTransactionData.getSignature());
-
return bytes.toByteArray();
} catch (IOException | ClassCastException e) {
throw new TransformationException(e);
diff --git a/src/v1feeder.java b/src/v1feeder.java
index 42d69f7f..a2c13a30 100644
--- a/src/v1feeder.java
+++ b/src/v1feeder.java
@@ -221,8 +221,8 @@ public class v1feeder extends Thread {
ValidationResult result = block.isValid();
if (result != ValidationResult.OK) {
- LOGGER.error("Invalid block, validation result code: " + result.value);
- throw new RuntimeException("Invalid block, validation result code: " + result.value);
+ LOGGER.error("Invalid block, validation result: " + result.name());
+ throw new RuntimeException("Invalid block, validation result: " + result.name());
}
block.process();